- 浏览: 5029047 次
- 性别:
- 来自: 南京
文章分类
- 全部博客 (2844)
- java (1094)
- hadoop (37)
- jvm (39)
- hbase (11)
- sql (25)
- 异常 (83)
- div css (6)
- 数据库 (95)
- 有趣的code (15)
- struts2 (6)
- spring (124)
- js (44)
- 算法 (65)
- linux (36)
- hibernate (7)
- 中间件 (78)
- 设计模式 (2)
- 架构 (275)
- 操作系统 (91)
- maven (35)
- tapestry (1)
- mybatis (9)
- MQ (101)
- zookeeper (18)
- 搜索引擎,爬虫 (208)
- 分布式计算 (45)
- c# (7)
- 抓包 (28)
- 开源框架 (45)
- 虚拟化 (12)
- mongodb (15)
- 计算机网络 (2)
- 缓存 (97)
- memcached (6)
- 分布式存储 (13)
- scala (5)
- 分词器 (24)
- spark (104)
- 工具 (23)
- netty (5)
- Mahout (6)
- neo4j (6)
- dubbo (36)
- canal (3)
- Hive (10)
- Vert.x (3)
- docker (115)
- 分布式追踪 (2)
- spring boot (5)
- 微服务 (56)
- 淘客 (5)
- mesos (67)
- php (3)
- etcd (2)
- jenkins (4)
- nginx (7)
- 区块链 (1)
- Kubernetes (92)
- 驾照 (1)
- 深度学习 (15)
- JGroups (1)
- 安全 (5)
- 测试 (16)
- 股票 (1)
- Android (2)
- 房产 (1)
- 运维 (6)
- 网关 (3)
最新评论
-
明兜3号:
部署落地+业务迁移 玩转k8s进阶与企业级实践技能(又名:Ku ...
Kubernetes系统常见运维技巧 -
q328965539:
牛掰啊 资料收集的很全面
HDFS小文件处理解决方案总结+facebook(HayStack) + 淘宝(TFS) -
guichou:
fluent挂载了/var/lib/kubelet/pods目 ...
kubernetes上部署Fluentd+Elasticsearch+kibana日志收集系统 -
xu982604405:
System.setProperty("java.r ...
jmx rmi 穿越防火墙问题及jmxmp的替代方案 -
大漠小帆:
麻烦问下,“获取每个Item相似性最高的前N个Item”,这个 ...
协同过滤推荐算法在MapReduce与Spark上实现对比
SpringSecurity 源码分析一
- 博客分类:
- spring
通过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在说吧。。。。。
发表评论
-
spring session序列化问题排查
2017-12-01 19:07 6264严重: Servlet.service() for ser ... -
spring mvc统一异常处理(@ControllerAdvice + @ExceptionHandler)
2017-12-01 17:09 2998spring 封装了非常强大的异常处理机制。本文选取@Co ... -
springboot注解
2017-12-01 09:44 1016@RestController和@RequestMappin ... -
Spring 4 xml 注解配置谅解
2017-12-01 09:39 1110《Spring in Action》4th E ... -
利用junit对springMVC的Controller进行测试
2017-11-30 16:26 1441平时对junit测试service/D ... -
spring cloud config实现datasource的热部署
2017-11-21 16:44 1615关于spring cloud config的基本使用,前面的 ... -
Spring+MyBatis实现数据库读写分离方案
2017-11-20 17:15 1075百度关键词:spring mybatis 多数据源 读写分离 ... -
spring session 退出登录 清理session
2017-11-10 09:26 6469/** * Allows creating an ... -
spring http session 监听 创建 失效session
2017-11-15 09:35 4870一.流程概述 主要是通过扩展ServletRequest ... -
spring session spring:session:sessions:expires 源码跟踪
2017-11-14 09:37 1500/** * Saves any attribut ... -
spring session 考虑问题解答
2017-11-09 09:50 647相关问题 2.Redis容量考虑,由于spring see ... -
spring 获取bean 测试
2017-11-09 09:51 665package com.jayway.springsess ... -
spring父子容器与读取properties文件
2017-11-09 09:51 821读取properties文件中的内容,可以使用@Value ... -
Spring在代码中获取bean的几种方式
2017-11-08 09:46 1219方法一:在初始化时保存ApplicationContext对 ... -
Spring中DispacherServlet、WebApplicationContext、ServletContext的关系
2017-11-08 09:41 815解释一: 要想很好理解这三个上下文的关系,需 ... -
Spring以及SPringmvc相关问题: ServletContext -父子容器
2017-11-08 09:41 615总结如下: 明确了Servlet规范中Servl ... -
DelegatingFilterProxy
2017-11-08 09:48 1207摘要: 配置过滤器代理类,通过spring配置的bean来 ... -
DelegatingFilterProxy-api
2017-11-09 09:51 551为什么用DelegatingFilterProxy ... -
spring的启动过程——spring和springMVC父子容器的原理
2017-11-15 09:29 715要想很好理解这三个上下文的关系,需要先熟悉spri ... -
spring中bean被多次实例化问题
2017-11-13 09:33 52121. 描述 spring中提供了两种主要方式实例化bea ...
相关推荐
### Spring Security 源码分析知识点 #### 一、Spring Security 概述 Spring Security 是一个强大且可高度定制的身份验证和访问控制框架。它提供了许多功能,包括登录表单、记住密码、CSRF 保护等。为了更好地理解...
在学习SpringSecurity源码时,建议从以下几个方面入手: 1. **源码结构分析**:了解主要组件的类结构和它们之间的关系,如`Authentication`、`Authorization`、`FilterChainProxy`等。 2. **关键类的实现**:深入...
在深入分析SpringSecurity源码之前,我们先了解一些基础概念。 1. DelegatingFilterProxy:这是一个Spring框架提供的过滤器,它作为代理来调用实际的Filter。在web.xml中,filter-name设置为...
通过阅读《Spring Security3.pdf》和《spring security3 源码分析.pdf》这两份文档,你可以对Spring Security 3的内部工作机制有更深入的理解,从而更好地在项目中运用这个强大的安全框架。同时,这也会帮助你在面临...
Spring Security源码分析一:Spring Security 认证过程 Spring Security源码分析二:Spring Security 授权过程 Spring Security源码分析三:Spring Social 实现QQ社交登录 Spring Security源码分析四:Spring Social...
总结,Spring Security 3的源码分析是一个深度学习的过程,涵盖了安全领域的多个方面。通过理解其内部工作机制,开发者可以更好地利用这一强大的框架,为应用程序提供安全的保障。同时,源码分析也能帮助开发者解决...
1. **Spring Security 基本架构**: Spring Security 由多个组件构成,包括过滤器链、访问决策管理器、安全上下文持有者等。核心组件是`DelegatingFilterProxy`,它是一个Servlet过滤器,用于代理其他Spring Bean...
SpringSecurity是Java开发中用于构建安全Web应用的框架,它提供了强大的身份验证、...在学习过程中,分析提供的源代码和示例将有助于深入理解SpringSecurity的工作原理,并能帮助你在实际项目中有效地应用这些知识。
通过分析这些源码,我们可以深入理解OAuth的工作原理,以及Spring Security OAuth如何支持这些功能。同时,Sparklr2和Tonr2示例能帮助我们直观地看到OAuth流程的每个步骤,包括授权、令牌交换和资源访问。 在实际...
SpringBoot_SpringSecurity-源码.zip 这个压缩包文件主要包含了SpringBoot集成SpringSecurity的源码分析。SpringBoot是Java开发中一个流行的轻量级框架,它简化了配置和应用部署,使得开发者可以快速搭建应用程序。...
本篇文章将深入探讨Spring Security的核心概念和源码分析。 1. **核心组件** - `SecurityContextHolder`: 它是Spring Security的核心,存储当前请求的安全上下文,包含认证信息和权限。 - `Authentication`: 表示...
在这个源码分析中,我们将聚焦于 `ConfigAttributeDefinition` 类,它是Spring Security配置核心组件的一部分。 `ConfigAttributeDefinition` 类扮演着配置属性的容器角色。它用于封装一系列的 `ConfigAttribute` ...
- 通过源码分析,了解Spring Security的拦截器如何工作,以及如何自定义安全规则。 - 查看`SecurityConfig`类,这是Spring Security的核心配置,它扩展了`WebSecurityConfigurerAdapter`并覆盖了一些关键方法。 -...
Java流行框架源码分析:Spring源码、SpringBoot源码、SpringAOP源码、SpringSecurity源码、SpringSecurity OAuth2源码、JDK源码、Netty源码
在分析Spring Security源码时,你可能会关注以下关键组件: - `AbstractSecurityInterceptor`:所有安全拦截器的基类。 - `FilterSecurityInterceptor`:处理HTTP请求的安全过滤器。 - `AuthenticationManager` 和 `...
通过对`spring-security-3.0.5.RELEASE`源码的分析,我们可以了解每个类和接口的作用,学习如何扩展和配置Spring Security以满足特定需求。这包括理解`@Configuration`和`@EnableGlobalMethodSecurity`注解如何启用...
Spring Security OAuth2 是一个强大的框架,用于为Java应用提供OAuth2和OpenID Connect...通过阅读和分析`spring-security-oauth-master`中的源码,可以更深入地了解其实现细节,有助于在实际项目中灵活运用和定制。
这个压缩包提供了Spring Security 3.1.3的源码,以及一个名为"sample"的示例项目,帮助开发者理解和学习如何在实际应用中使用这个库。 **1. Spring Security的基本架构** Spring Security基于过滤器链的概念,其...
1. **Spring 事务处理**:Spring 提供了声明式事务管理,允许开发者在配置文件中定义事务边界,无需在业务逻辑代码中显式控制事务开始、提交和回滚。它主要基于AOP代理来实现,通过TransactionInterceptor拦截器进行...
`springsecurity-sample.rar` 可能包含一个示例项目,展示如何集成 Spring Security 并进行基本配置。这个样本项目可能包括以下部分: 1. **SecurityConfig**: 定义安全规则的 Java 类,可能使用 `@...