Spring Security 架构

最近开始准备做一个项目,找了慕课的权限管理系统,开始学习spring seurity框架,这里记录一下这个框架的架构

是什么

一个能够为基于Spring的企业应用系统提供声明式的安全訪问控制解决方式的安全框架(简单说是对访问权限进行控制嘛),应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。 spring security的主要核心功能为 认证和授权,所有的架构也是基于这两个核心功能去实现的。

简单来说:Spring Security 主要实现了Authentication(认证,解决who are you? ) 和 Access Control(访问控制,也就是what are you allowed to do?,也称为Authorization)。Spring Security在架构上将认证与授权分离,并提供了扩展点。

核心对象

首先我们看一下Spring Security中的三个核心对象SecurityContextHolder, SecurityContext 和 Authentication

SecurityContextHolder是SecurityContext的存放容器,使用ThreadLocal存储,意味着SecurityContext在相同的线程中的方法都是可用的。
SecurityContext主要的存储应用的principal信息,然后在Spring Security中用 Authentication来表示。

这里贴上获取principal的方式

Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();if (principal instanceof UserDetails) {
String username = ((UserDetails)principal).getUsername();
} else {
String username = principal.toString();
}

然后我们看一下对于Authentication的定义

public interface Authentication extends Principal, Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();            //通常是密码

    Object getCredentials();       //更多细节信息来标识用户,可能是ip地址

    Object getDetails();        //标识是否已经认证,如果是用户密码登陆则这里通常是用户名

    Object getPrincipal();      //是否认证

    boolean isAuthenticated();

    void setAuthenticated(boolean var1) throws IllegalArgumentException;
}

一个常见的认证过程通常是这样的,创建一个UsernamePasswordAuthenticationToken,然后交给authenticationManager认证,认证通过SecurityContextHolder存放Authentication的信息

UserDetails与UserDetailService

UserDetails是Spring Security里的一个关键接口,他表示一个principal

public interface UserDetails extends Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();

    String getPassword();

    String getUsername();

    boolean isAccountNonExpired();

    boolean isAccountNonLocked();

    boolean isCredentialsNonExpired();

    boolean isEnabled();
}

UserDetails 提供了认证所需的必要信息,在实际使用里,可以自己实现UserDetails,并增加额外的信息,比如email、mobile等信息。

在Authentication中的principal的通常是用户名,我们可以通过UserDetailService获取UserDetails;

小结

  • SecurityContextHolder, 用来访问 SecurityContext.

  • SecurityContext, 用来存储Authentication .

  • Authentication, 代表凭证.

  • GrantedAuthority, 代表权限.

  • UserDetails, 用户信息.

  • UserDetailsService,获取用户信息.

web security的实现方式

Web层中的Spring Security(用于UI和HTTP后端)基于Servlet Filters,下图显示了单个HTTP请求的处理程序的典型分层。
在这里插入图片描述
Spring Security通过FilterChainProxy作为单一的Filter注册到web层,Proxy内部的Filter。
在这里插入图片描述
FilterChainProxy相当于一个filter的容器,通过VirtualFilterChain来依次调用各个内部filter

不同的filter拦截器

1.SecurityContextPersistenceFilter

  • 位于过滤器的顶端,是起作用的第一层过滤器,在别的过滤器之前率先判断session是否存在上下文
SecurityContext contextBeforeChainExecution = this.repo.loadContext(holder);
  • 在所有过滤器之后清空spring security内容
 SecurityContextHolder.clearContext();

2.LogoutFilter 用户发送注销请求时候清空session和applicationContext,同时可以配合其他的去清空cookie

3.AbstractAuthenticationProcessingFilter 处理form登陆的过滤器

与form有关的所有登陆在此执行,判断用户名和密码然后跳转对应成功和错误

4.DefaultLoginPageGeneratingFiler 默认登陆页面(丑)

5.BaseicAuthenticationFilter 与AbstractAuthenticationProcessingFilter 类似,只是验证的方式不同

6.SecurityContextHolderAwareRequestFilter 用来包装客户的信息,用来返回对应get/set

7.RememberMeAuthenticationFilter 通过cookie免登陆

8.AnoymousAuthenticationFilter 匿名登陆

9.ExceptionTranslation 异常控制

10.SessionManagementFilter 防止攻击

11.FilterSecurityInterceptor

核心处理流程

在这里插入图片描述

数据库管理
  • 当一个用户登陆时候,先执行身份认证,如果认证未通过,重新认证。
  • 当用户认证通过,调用角色管理器判断他能否访问,这里就是用到spring security提供的UserDetails,Authentication是spring security使用的安全访问控制用户信息的安全对象,这里的UserDetails是用户的信息原
  • 当我们需要使用数据库管理用户时候,我们需要手动实现UserDetailsService接口中的loadUserByUsername方法,这就需要我们在数据库中准备3张表:用户表、权限表、角色表、用户和角色关系表、权限和角色关系表。
  • 这样我们就把用户登陆放到数据库中管理了
权限缓存

CachingUserDetailService类

  • 这个类的构造方法接收了用于真正加载UserDetails的UserDetailsService实现类
  • 当需要UserDeatils时候,会优先从缓存中获取,如果缓存中没有Details存在,就会用UserDetailsService的实现类来加载,然后存在缓存中
  • Details跟缓存的交互就是通过UserCache来实现

实际项目中,会使用别的缓存,redis之类来缓存别的信息。

自定义决策

当用户通过认证,调用决策管理器AbstractAccessDecisionManager,其中有判断方法supports,其中的参数decisionVoters类型是AccessDesionvoter,他是spring security引入的投票器的概念,最终决定权就是投票器决定

RoleVoter中vote方法会循环判断是否通过,最终返回ACCESS_GRANTED

目前三种投票器:

  • AffirmativeBased(一票通过)
  • ConsensusBased(半数通过)
  • UnanimousBased(全数通过)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值