SpringSecurity读书笔记01

SpringSecurity的核心功能:

        1.认证:即身份认证(你是谁?)

                

        

        2.授权:即访问控制(你可以做什么)

SpringSecurity整体架构:

        1.认证:

                在SpringSecurity种,用户的认证信息主要是由Authentication的实现类来保存的,Authentication的接口定义为

public interface Authentication extends Principal, Serializable {
 Collection<? extends GrantedAuthority> getAuthorities();
 Object getCredentials();
 Object getDetails();
 Object getPrincipal();
 boolean isAuthenticated();
 void setAuthenticated(boolean isAuthenticated);
}

   这里接口定义的方法有:

  •  getAuthorities 方法:用来获取用户的权限。
  • getCredentials 方法:用来获取用户凭证,一般来说就是密码。
  •  getDetails 方法:用来获取用户携带的详细信息,可能是当前请求乊类等。
  •  getPrincipal 方法:用来获取当前用户,例如是一个用户名或者一个用户对象。
  •  isAuthenticated:当前用户是否认证成功。

当用户使用用户名/密码登录或者使用Remember-me登录时,都会对应一个Authentication实例

当把认证信息保存了之后,当用户来登录时,需要进行认证工作,这个工作交给了由 AuthenticationManager 接口来负责,下面是该接口的定义

public interface AuthenticationManager {
 Authentication authenticate(Authentication authentication)
 throws AuthenticationException;
}

   AuthenticationManager只有一 authenticate 方法可以用来做认证,该方法有三个返回值:

  • 返回Authentication,表示认证成功
  • 返回AuthenticationException异常,表示用户输入无效的凭证
  • 返回null,表示不能确定

AuthenticationManager最主要的实现类是ProviderManager,ProviderManager,管理了众多的AuthenticationProvider实例,而AuthenticationProvider又处理了众多的Authentication的实现类,这些不同的实现类,需要不同的AuthenticationProvider来进行处理,所以在AuthenticationProvider中提供了一个supports方法,来判断是否支持给定的Authentication类型。

在一次完整的认证流程中,可能会同时存在多个 AuthenticationProvider(例如,项目同时
支持 form 表单登录和短信验证码登录),多个 AuthenticationProvider 统一ProviderManager 来管理。同时,ProviderManager 具有一个可选的 parent,如果所有的 AuthenticationProvider 都认证失败,那么就会调用 parent 进行认证。parent 相当于一个备用认证方式,即各个 AuthenticationProvider 都无法处理认证问题的时候,就由 parent 出场收拾残局。

        2. 授权:

                        当完成认证之后,接下来就是授权了,在SpringSecurity的授权体系中有两个关键接口:

  • AccessDecisionManager     
  • AccessDecisionVoter

AccessDecisionVoter是一个投票器,投票器会检查用户是否具备应有的角色,进而投出赞成,反对或者弃权,AccessDecisionManager  则是一个决策器,来决定此次访问是否被允许。

AccessDecisionManager 中会挨个遍历AccessDecisionVoter,进而决定是否允许用户访问。

在SpringSecurity中,用户请求的资源(通常是一个网络接口或者一个java方法)所需要的角色都被封装成一个ConfigAttribute对象,在ConfigAttribute中只有一个getAttribute方法,这个方法返回一个字符串,就是角色的名称,一个来说,角色名称都带有一个ROLE_前缀,投票器AccessDecisionVoter所做的事情,其实就是比较用户所具备的角色和请求某个资源所需的ConfigAttribute之间的关系

        3.web安全:

                             SpringSecurity的基本原理:SpringSecurity的认证,授权等功能都是基于过滤器来实现的。在SpringSecurity中会配置很多的过滤器,这些过滤器按照既定的优先级排列,最终形成一个过滤器链,开发者还可以自定义过滤器,并通过@Order注解去调整自定义过滤器在过滤器链中的位置。

               需要注意的是,SpringSecurity默认加载的过滤器,并不是直接放在Web项目的原生过滤器链中,而是通过一个FilterChainProxy来统一管理。SpringSecurity中的过滤器链通过FilterChainProxy嵌入到Web项目的原生过滤器中,如图1-1所示。

SpringSecurity中,这样的过滤器链不仅仅只有一个,可能有很多个,当存在多个过滤器链时,多个过滤器链之间需要指定优先级,当请求到达后,会通过FilterChainProxy进行分发,先和哪个过滤器链匹配上,就用哪个过滤器进行处理,当系统中存在不同的认证体系时,那么使用多个过滤器连接就非常有效

FilterChainProxy 作为一个顶层管理者,将统一管理 Security FilterFilterChainProxy 本身
将通过 Spring 框架提供的 DelegatingFilterProxy 整合到原生过滤器链中,所以图 1-2 还可以做
进一步的优化,如图 1-3 所示

 

 

 

登录数据保存

如果不使用 Spring Security 这一类的安全管理框架,大部分的开发者可能会将登录用户数
据保存在Session中,事实上,Spring Security也是这么做的。但是,为了使用方便,Spring Security 在此基础上还做了一些改进,其中最主要的一个变化就是线程绑定。 当用户登录成功后,Spring Security 会将登录成功的用户信息保存到 SecurityContextHolder 中。SecurityContextHolder 中的数据保存默认是通过 ThreadLocal 来实现的,使用 ThreadLocal
创建的变量只能被当前线程访问,不能被其他线程访问和修改,也就是用户数据和请求线程绑
定在一起。当登录请求处理完毕后,Spring Security 会将 SecurityContextHolder 中的数据拿出
来保存到 Session 中,同时将 SecurityContextHolder 中的数据清空。以后每当有请求到来时,
Spring Security 就会先从 Session 中取出用户登录数据,保存到 SecurityContextHolder 中,方便 在该请求的后续处理过程中使用,同时在请求结束时将 SecurityContextHolder 中的数据拿出来 保存到 Session 中,然后将 SecurityContextHolder 中的数据清空。 这一策略非常方便用户在 Controller 或者 Service 层获取当前登录用户数据,但是带来的 另外一个问题就是,在子线程中想要获取用户登录数据就比较麻烦。Spring Security 对此也提 供了相应的解决方案,如果开发者使用@Async 注解来开启异步任务的话,那么只需要添加如 下配置,使用 Spring Security 提供的异步任务代理,就可以在异步任务中从 Security ContextHolder 里边获取当前登录用户的信

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值