`
m635674608
  • 浏览: 5029047 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

SpringSecurity 源码分析一

阅读更多
 

    通过SecurityContextHolder.getContext()获得SecurityContext
   总接口SecurityContextHolderStrategy

private static void initialize() {
        if ((strategyName == null) || "".equals(strategyName)) {
            // Set default
            strategyName = MODE_THREADLOCAL;
        }

        if (strategyName.equals(MODE_THREADLOCAL)) {
            strategy = new ThreadLocalSecurityContextHolderStrategy();
        } else if (strategyName.equals(MODE_INHERITABLETHREADLOCAL)) {
            strategy = new InheritableThreadLocalSecurityContextHolderStrategy();
        } else if (strategyName.equals(MODE_GLOBAL)) {
            strategy = new GlobalSecurityContextHolderStrategy();
        } else {
            // Try to load a custom strategy
            try {
                Class clazz = Class.forName(strategyName);
                Constructor customStrategy = clazz.getConstructor(new Class[] {});
                strategy = (SecurityContextHolderStrategy) customStrategy.newInstance(new Object[] {});
            } catch (Exception ex) {
                ReflectionUtils.handleReflectionException(ex);
            }
        }

        initializeCount++;
    }       

当SecurityContextHolder初始化的时候。判断调用哪个SecurityContextHolderStrategy的实现类

Authentication auth = SecurityContextHolder.getContext().getAuthentication();

让后通过 SecurityContext 接口 实现类 SecurityContextImpl  获得    getAuthentication()的到Authentication 对象,Authentication 对象中装了很多用户信息




 
 

 

Authentication 主要是包括一些用户认证的信息,比如权限啊。名字啊什么的。。。

Springsecurity 主要是 认证+授权+filter

认证 分 证管理器+认证者。

认证管理器(org.springframework.security.AuthenticationManager接口



 

 

 

 

public class ProviderManager extends AbstractAuthenticationManager implements InitializingBean, MessageSourceAware,
        ApplicationEventPublisherAware  {
    //~ Static fields/initializers =====================================================================================

    private static final Log logger = LogFactory.getLog(ProviderManager.class);
    private static final Properties DEFAULT_EXCEPTION_MAPPINGS = new Properties();

    //~ Instance fields ================================================================================================

    private ApplicationEventPublisher applicationEventPublisher;
    private ConcurrentSessionController sessionController = new NullConcurrentSessionController();
    private List providers;
    protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
    private Properties exceptionMappings = new Properties();
    private Properties additionalExceptionMappings = new Properties();
  <!-- 认证管理器(org.springframework.security.AuthenticationManager接口) org.springframework.security.providers.ProviderManager是认证管理器的一个实现, ProviderManager通过遍历一个提供者的集合来实现身份验证, 直到某一个认证提供者能够成功地验证该用户的身份 --> <!-- 通过Providers提供认证者列表,如果一个认证提供者失败可以尝试另外一个认证提供者,以保证获取不同来源的身份认证,如 DaoAuthenticationProvider 从数据库中读取用户信息验证身份 AnonymousAuthenticationProvider 匿名用户身份认证 RememberMeAuthenticationProvider 已存cookie中的用户信息身份认证 其它的还有 AuthByAdapterProvider 使用容器的适配器验证身份 CasAuthenticationProvider 根据Yale中心认证服务验证身份, 用于实现单点登陆 JaasAuthenticationProvider 从JASS登陆配置中获取用户信息验证身份 RemoteAuthenticationProvider 根据远程服务验证用户身份 RunAsImplAuthenticationProvider 对身份已被管理器替换的用户进行验证 X509AuthenticationProvider 从X509认证中获取用户信息验证身份 TestingAuthenticationProvider 单元测试时使用 每个认证者会对自己指定的证明信息进行认证,如DaoAuthenticationProvider仅对UsernamePasswordAuthenticationToken这个证明信息进行认证。 总接口 AuthenticationManager 管理器 装着 很多个AuthenticationProvider 管理者--> <bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager" p:sessionController-ref="concurrentSessionController"> <!-- private List providers;<装着很多个认证器> --> <property name="providers"> <list> <ref bean="daoAuthenticationProvider"/> <bean class="org.springframework.security.providers.anonymous.AnonymousAuthenticationProvider" p:key="springsecurity"/> <bean class="org.springframework.security.providers.rememberme.RememberMeAuthenticationProvider" p:key="springsecurity"/> </list> </property> </bean>

  可以看出一个认证器里面包含了多个认证者

下面来看看认证者接口

 

public interface AuthenticationProvider {
    //~ Methods ========================================================================================================

    /**
     * Performs authentication with the same contract as {@link
     * org.springframework.security.AuthenticationManager#authenticate(Authentication)}.
     *
     * @param authentication the authentication request object.
     *
     * @return a fully authenticated object including credentials. May return <code>null</code> if the
     *         <code>AuthenticationProvider</code> is unable to support authentication of the passed
     *         <code>Authentication</code> object. In such a case, the next <code>AuthenticationProvider</code> that
     *         supports the presented <code>Authentication</code> class will be tried.
     *
     * @throws AuthenticationException if authentication fails.
     */
    Authentication authenticate(Authentication authentication)
        throws AuthenticationException;

   有一个认证方法。不同的实现类通过这个方法来认证用户。下面来看下DaoAuthenticationProvider认证者是怎么认证用户的。

public class DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

    //~ Instance fields ================================================================================================

    private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder();

    private SaltSource saltSource;

    private UserDetailsService userDetailsService;

    private boolean includeDetailsObject = true;


 protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {
        UserDetails loadedUser;

        try {
            loadedUser = this.getUserDetailsService().loadUserByUsername(username);
        }
        catch (DataAccessException repositoryProblem) {
            throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);
        }

        if (loadedUser == null) {
            throw new AuthenticationServiceException(
                    "UserDetailsService returned null, which is an interface contract violation");
        }
        return loadedUser;
    }

  DaoAuthenticationProvider认证者通过注入UserDetailsService来获取用户信息

<!-- 认证管理器  总接口AuthenticationProvider -->
	<bean id="daoAuthenticationProvider" 
		class="org.springframework.security.providers.dao.DaoAuthenticationProvider"
		p:passwordEncoder-ref="passwordEncoder"
		p:userDetailsService-ref="userDetailsService"/>

 UserDetailsService 就相当于我们的业务逻辑层 通过不同的方式获取用户信息  比如:

 

<!-- 获得userDetails的service  总接口UserDetailsService 子类-->
	 <bean id="userDetailsService" 
	 	class="org.springframework.security.userdetails.memory.InMemoryDaoImpl">
	 	<property name="userProperties">
	 		<bean class="org.springframework.beans.factory.config.PropertiesFactoryBean"
	 			p:location="/WEB-INF/users.properties"/>
	 	</property>

 通过properties文件来配置用户权限

admin=admin,ROLE_SUPERVISOR
user1=user1,ROLE_USER
user2=user2,ROLE_USER
user3=user3,disabled,ROLE_USER
#scott/wombat
scott=2b58af6dddbd072ed27ffc86725d7d3a,ROLE_USER

 

还可以这样:

<property name="userMap">
	 		<value>
	 			admin=admin,ROLE_SUPERVISOR
				user1=user1,ROLE_USER
				user2=user2,ROLE_USER
				user3=user3,disabled,ROLE_USER
	 		</value>
	 	</property>

 至于org.springframework.security.userdetails.memory.InMemoryDaoImpl 怎么封装,可想而知

 */
public class InMemoryDaoImpl implements UserDetailsService, InitializingBean {

    public void afterPropertiesSet() throws Exception {
        Assert.notNull(this.userMap,
            "A list of users, passwords, enabled/disabled status and their granted authorities must be set");
    }

    public UserMap getUserMap() {
        return userMap;
    }
    public UserDetails loadUserByUsername(String username)
        throws UsernameNotFoundException, DataAccessException {
        return userMap.getUser(username);
    }

    public void setUserMap(UserMap userMap) {
        this.userMap = userMap;
    }
    public void setUserProperties(Properties props) {
        UserMap userMap = new UserMap();
        this.userMap = UserMapEditor.addUsersFromProperties(userMap, props);
    }
}

 下面来看这个service有多少中实现方式。实现类



 看实现类名字就可以想到。可以通过jdbc配置在数据库中,InMemoryDaoImpl配置文件中(加载到内存)

 可以把用户信息放到Ldap。 UserDetailsService 通过loadUserByUsername方法加载用户信息

 

class CachingUserDetailsService implements UserDetailsService {
	private UserCache userCache = new NullUserCache();
	private UserDetailsService delegate;

	CachingUserDetailsService(UserDetailsService delegate) {
		this.delegate = delegate;
	}

	public UserCache getUserCache() {
		return userCache;
	}

	public void setUserCache(UserCache userCache) {
		this.userCache = userCache;
	}

	public UserDetails loadUserByUsername(String username) {
		UserDetails user = userCache.getUserFromCache(username);
		
		if (user == null) {
			user = delegate.loadUserByUsername(username);
		}
		
		Assert.notNull(user, "UserDetailsService " + delegate + " returned null for username " + username + ". " +
				"This is an interface contract violation");
		
		userCache.putUserInCache(user);
		
		return user;
	}
}

 还可以为实现类注入缓存默认是private UserCache userCache = new NullUserCache();

下面来看下springsecurity的缓存



 

springsecurity的缓存主要还是通过ehcache缓存实现的。只是封装了一下方法。下面请看UserCache实现类

public class EhCacheBasedUserCache implements UserCache, InitializingBean {
    //~ Static fields/initializers =====================================================================================

    private static final Log logger = LogFactory.getLog(EhCacheBasedUserCache.class);

    //~ Instance fields ================================================================================================

    private Ehcache cache;

    //~ Methods ========================================================================================================

    public void afterPropertiesSet() throws Exception {
        Assert.notNull(cache, "cache mandatory");
    }

    public Ehcache getCache() {
        return cache;
    }

    public UserDetails getUserFromCache(String username) {
        Element element = null;

        try {
            element = cache.get(username);
        } catch (CacheException cacheException) {
            throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage());
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Cache hit: " + (element != null) + "; username: " + username);
        }

        if (element == null) {
            return null;
        } else {
            return (UserDetails) element.getValue();
        }
    }

    public void putUserInCache(UserDetails user) {
        Element element = new Element(user.getUsername(), user);

        if (logger.isDebugEnabled()) {
            logger.debug("Cache put: " + element.getKey());
        }

        cache.put(element);
    }

    public void removeUserFromCache(UserDetails user) {
        if (logger.isDebugEnabled()) {
            logger.debug("Cache remove: " + user.getUsername());
        }

        this.removeUserFromCache(user.getUsername());
    }

    public void removeUserFromCache(String username) {
        cache.remove(username);
    }

    public void setCache(Ehcache cache) {
        this.cache = cache;
    }
}

 在这里可以看到这些方法都是调用了ehcache里面的方法。 这里的   private Ehcache cache;是靠你在配置文件配的。注入进来的。

<bean class="org.springframework.security.providers.dao.cache.EhCacheBasedUserCache">
	  <property name="userCache" value="userCahce"></property>
	 </bean>

  SpringSecurity刚入门不久,主要把概率,理论弄清楚了。感觉还是比较容易的。让后在结合源码看一下。映像就深刻多了,今天就写到这了。下次在看下SpringSecurity的Filter在说吧。。。。。

 



 

  • 大小: 5.4 KB
  • 大小: 3.8 KB
  • 大小: 24.1 KB
  • 大小: 9.4 KB
  • 大小: 21.1 KB
  • 大小: 17.7 KB
  • 大小: 7 KB
分享到:
评论

相关推荐

    spring security源码分析.pdf

    ### Spring Security 源码分析知识点 #### 一、Spring Security 概述 Spring Security 是一个强大且可高度定制的身份验证和访问控制框架。它提供了许多功能,包括登录表单、记住密码、CSRF 保护等。为了更好地理解...

    SpringSecurity源码

    在学习SpringSecurity源码时,建议从以下几个方面入手: 1. **源码结构分析**:了解主要组件的类结构和它们之间的关系,如`Authentication`、`Authorization`、`FilterChainProxy`等。 2. **关键类的实现**:深入...

    3.springSecurity源码分析1

    在深入分析SpringSecurity源码之前,我们先了解一些基础概念。 1. DelegatingFilterProxy:这是一个Spring框架提供的过滤器,它作为代理来调用实际的Filter。在web.xml中,filter-name设置为...

    Spring Security 3 源码分析文档

    通过阅读《Spring Security3.pdf》和《spring security3 源码分析.pdf》这两份文档,你可以对Spring Security 3的内部工作机制有更深入的理解,从而更好地在项目中运用这个强大的安全框架。同时,这也会帮助你在面临...

    Android代码-logback

    Spring Security源码分析一:Spring Security 认证过程 Spring Security源码分析二:Spring Security 授权过程 Spring Security源码分析三:Spring Social 实现QQ社交登录 Spring Security源码分析四:Spring Social...

    Spring_Security3_源码分析

    总结,Spring Security 3的源码分析是一个深度学习的过程,涵盖了安全领域的多个方面。通过理解其内部工作机制,开发者可以更好地利用这一强大的框架,为应用程序提供安全的保障。同时,源码分析也能帮助开发者解决...

    springsecurity源码(鉴权有缺陷)

    1. **Spring Security 基本架构**: Spring Security 由多个组件构成,包括过滤器链、访问决策管理器、安全上下文持有者等。核心组件是`DelegatingFilterProxy`,它是一个Servlet过滤器,用于代理其他Spring Bean...

    SpringSecurity学习总结源代码

    SpringSecurity是Java开发中用于构建安全Web应用的框架,它提供了强大的身份验证、...在学习过程中,分析提供的源代码和示例将有助于深入理解SpringSecurity的工作原理,并能帮助你在实际项目中有效地应用这些知识。

    Spring security oauth源码

    通过分析这些源码,我们可以深入理解OAuth的工作原理,以及Spring Security OAuth如何支持这些功能。同时,Sparklr2和Tonr2示例能帮助我们直观地看到OAuth流程的每个步骤,包括授权、令牌交换和资源访问。 在实际...

    SpringBoot_SpringSecurity-源码.rar

    SpringBoot_SpringSecurity-源码.zip 这个压缩包文件主要包含了SpringBoot集成SpringSecurity的源码分析。SpringBoot是Java开发中一个流行的轻量级框架,它简化了配置和应用部署,使得开发者可以快速搭建应用程序。...

    spring security 源码

    本篇文章将深入探讨Spring Security的核心概念和源码分析。 1. **核心组件** - `SecurityContextHolder`: 它是Spring Security的核心,存储当前请求的安全上下文,包含认证信息和权限。 - `Authentication`: 表示...

    Spring_Security源码分析

    在这个源码分析中,我们将聚焦于 `ConfigAttributeDefinition` 类,它是Spring Security配置核心组件的一部分。 `ConfigAttributeDefinition` 类扮演着配置属性的容器角色。它用于封装一系列的 `ConfigAttribute` ...

    spring security 项目配置源码

    - 通过源码分析,了解Spring Security的拦截器如何工作,以及如何自定义安全规则。 - 查看`SecurityConfig`类,这是Spring Security的核心配置,它扩展了`WebSecurityConfigurerAdapter`并覆盖了一些关键方法。 -...

    Java流行框架源码分析:Spring源码、SpringBoot源码、SpringAOP源码、SpringSecurity源码、

    Java流行框架源码分析:Spring源码、SpringBoot源码、SpringAOP源码、SpringSecurity源码、SpringSecurity OAuth2源码、JDK源码、Netty源码

    Spring Security 源码

    在分析Spring Security源码时,你可能会关注以下关键组件: - `AbstractSecurityInterceptor`:所有安全拦截器的基类。 - `FilterSecurityInterceptor`:处理HTTP请求的安全过滤器。 - `AuthenticationManager` 和 `...

    spring-security3.0.5源码

    通过对`spring-security-3.0.5.RELEASE`源码的分析,我们可以了解每个类和接口的作用,学习如何扩展和配置Spring Security以满足特定需求。这包括理解`@Configuration`和`@EnableGlobalMethodSecurity`注解如何启用...

    spring-security-oauth2源码

    Spring Security OAuth2 是一个强大的框架,用于为Java应用提供OAuth2和OpenID Connect...通过阅读和分析`spring-security-oauth-master`中的源码,可以更深入地了解其实现细节,有助于在实际项目中灵活运用和定制。

    spring security 3.1.3 源码含sample源码

    这个压缩包提供了Spring Security 3.1.3的源码,以及一个名为"sample"的示例项目,帮助开发者理解和学习如何在实际应用中使用这个库。 **1. Spring Security的基本架构** Spring Security基于过滤器链的概念,其...

    spring源码分析(1-10)

    1. **Spring 事务处理**:Spring 提供了声明式事务管理,允许开发者在配置文件中定义事务边界,无需在业务逻辑代码中显式控制事务开始、提交和回滚。它主要基于AOP代理来实现,通过TransactionInterceptor拦截器进行...

    Spring-Security安全权限管理手册+源码

    `springsecurity-sample.rar` 可能包含一个示例项目,展示如何集成 Spring Security 并进行基本配置。这个样本项目可能包括以下部分: 1. **SecurityConfig**: 定义安全规则的 Java 类,可能使用 `@...

Global site tag (gtag.js) - Google Analytics