SpringSecurity核心功能详解

2022年6月2日13:25:41

前言

最近在潜心研究一下安全框架,并在此进行一下记录,如有不对还请不吝赐教。

对于一个安全管理管理框架而言,无论是Shiro还是SpringSecurity,最核心的功能,无非就是两个

  • 认证:你是谁?
  • 授权:你可以做什么

认证

SpringSecurity支持多种不同的认证方式,这些认证方式有的是SpringSecurity自己提供的认证功能,有的是第三方标准组织制定的。SpringSecurity集成的主流认证机制主要有如下几种:

  • 表单认证
  • OAuth2.0认证
  • SAML2.0认证
  • CAS认证
  • RememberMe自动认证
  • JAAS认证
  • OpenID认证
  • Pre-Authentication Scenarios认证
  • X509认证
  • HTTP Basic认证
  • HTTP Digest认证

作为一个开放的平台,SpringSecurity提供的认证机制不仅仅包括上面,我们还可以通过引入第三方依赖来支持更多的认证方式,同时,如果这些认证方式无法满足我们的需求,我们也可以自定义认证逻辑,特别是当我们和一些“老破旧”的系统进行集成时,自定义认证就显得非常重要了。

授权

无论采用了上面哪种方式认证,都不影响在SpringSecurity中使用授权功能。SpringSecurity支持基于URL的请求授权,支持方法的访问授权,支持SpEL访问控制,支持域对象安全,同时也支持动态权限配置、支持RBAC权限模型等,总之,我们常见的权限管理需求,SpringSecurity基本上都是支持的。

其他

在认证和授权这两个核心功能之外,SpringSecurity还提供了很多安全管理的“周边功能”,这也是一个非常重要的特色,在开发中,即便我们不了解很多网络攻击,只要用了SpringSecurity它会帮助我们自动防御很多网络攻击,例如CSRF攻击,会话固定攻击等,同时还提供了HTTP防火墙来拦截大量的非法请求。

认证和授权

认证

在SpringSecurity的架构设计中,认证(Authentication)和授权(Authorization)是分开的,无论使用什么样的认证方式,都不会影响授权,这是两个独立的存在,这种独立带来的好处之一,就是可以非常方便地整合一些外部地认证方案。

在SpringScuerity中,用户地认证信息主要是由Authentication的实现类来保存,接口定义如下:

publicinterfaceAuthenticationextendsPrincipal, Serializable{//用来获取用户的权限
	Collection<?extendsGrantedAuthority>getAuthorities();//用来获取用户凭证,一般来说是密码
	ObjectgetCredentials();//用来获取用户携带的详细信息,可能是当前请求之类等
	ObjectgetDetails();//用来获取当前用户,例如是一个用户或一个用户对象
	ObjectgetPrincipal();//当前用户是否认证成功。booleanisAuthenticated();voidsetAuthenticated(boolean isAuthenticated)throws IllegalArgumentException;}

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

SpringSecurity中的认证工作主要由AuthenticationManager接口负责,我们来看一下该接口的定义

publicinterfaceAuthenticationManager{

	Authenticationauthenticate(Authentication authentication)throws AuthenticationException;}

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

  • 返回Authentication : 表示认证成功

  • 抛出AuthenticationException异常:表示用户输入了无效的凭证.

  • 返回null,表示不能断定

    AuthenticationManager最主要的实现类是ProviderManager,ProviderManager管理了众多的AuthenticationProvider实例,AuthenticationProvider有点类似于AuthenticationManager,但是它多了一个supports方法用来短评是否指出给定的Authenticaion类型。

publicinterfaceAuthenticationProvider{

	Authenticationauthenticate(Authentication authentication)throws AuthenticationException;booleansupports(Class<?> authentication);}

由于Authentication拥有众多不同的实现类,这些不同的实现类又由不能的AuthenticationProvider来处理,所以AuthenticationProvider会有一个supports方法,来判断当前的AuthenticationProvider是否支持对应的Authentication

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

授权

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

  • AccessDecisionManager
  • AccessDecisionVoter

AccessDecisionVoter是一个投票器,拉票器会检查用户是否具备应有的角色,进而投出赞成、反对或者弃权票,AccessDecisionManager则是一个决策器,来决定此次访问是否被允许。AccessDecisionVoter和AccessDecisionManager都有众多的实现类,在AccessDecisionManager中会挨个遍历AccessDecisionVoter,进而决定是否允许用户访问,因为AccessDecisionVoter和AccessDecisionManager两者的关系类似于AuthenticationProvider和ProviderManager的关系。

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

  • 作者:陈橙橙丶
  • 原文链接:https://chenxh.blog.csdn.net/article/details/123400408
    更新时间:2022年6月2日13:25:41 ,共 3107 字。