文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring Security认证机制是什么

2023-07-05 17:33

关注

这篇“Spring Security认证机制是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Spring Security认证机制是什么”文章吧。

Spring Security提供如下几种认证机制

这里使用Spring Boot 2.7.4版本,对应Spring Security 5.7.3版本

Servlet Authentication Architecture

首先明确两个概念:

Spring Security提供了以下几个核心类:

Spring Security认证机制是什么

SecurityContextHolder

先来看一个使用SecurityContextHolder和SecurityContext完成认证的案例:

SecurityContext context = SecurityContextHolder.createEmptyContext();// 手动生成一个Authentication,实际一般是通过数据库查出来生成的Authentication authentication =    new TestingAuthenticationToken("username", "password", "ROLE_USER");context.setAuthentication(authentication);SecurityContextHolder.setContext(context);

默认 情况下 SecurityContext存储使用ThreadLocal方式,这个就是ThreadLocal的一个用处,避免函数间参数传递的复杂性,只要处于一个线程,就可以直接获取而不需要通过函数参数返回值来传递。

注意:在使用ThreadLocal时,由于键是其this本身,是一个弱引用,而值只能是强引用,所以ThreadLocal不用时需要手动clear。而Spring Security中,在 FilterChainProxy中完成这一清除工作,如下:

public class FilterChainProxy extends GenericFilterBean {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {...try {...// 执行Spring Security 的 SecurityFilterChaindoFilterInternal(request, response, chain);}catch (Exception ex) {...}finally {// ***************// 清除ThreadLocal// ***************SecurityContextHolder.clearContext();request.removeAttribute(FILTER_APPLIED);}}}

但有些情形是用不了ThreadLocal的,For example, a Swing client might want all threads in a Java Virtual Machine to use the same security context 。针对其他情况,SecurityContextHolder提供了4种模式,当然也可以自定义:

可以通过2种方式去修改模式:

public class SecurityContextHolder {// 存储SecurityContext的模式,默认 ThreadLocal存储public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL";public static final String MODE_INHERITABLETHREADLOCAL = "MODE_INHERITABLETHREADLOCAL";public static final String MODE_GLOBAL = "MODE_GLOBAL";private static final String MODE_PRE_INITIALIZED = "MODE_PRE_INITIALIZED";public static final String SYSTEM_PROPERTY = "spring.security.strategy";// 通过系统参数指定 存储模式private static String strategyName = System.getProperty(SYSTEM_PROPERTY);// 实际存储SecurityContext的接口(类)private static SecurityContextHolderStrategy strategy;private static int initializeCount = 0;static {// 初始化initialize();}private static void initialize() {initializeStrategy();initializeCount++;}private static void initializeStrategy() {...if (!StringUtils.hasText(strategyName)) {// Set default 默认 ThreadLocalstrategyName = MODE_THREADLOCAL;}if (strategyName.equals(MODE_THREADLOCAL)) {strategy = new ThreadLocalSecurityContextHolderStrategy();return;}...}// 修改Strategypublic static void setStrategyName(String strategyName) {SecurityContextHolder.strategyName = strategyName;initialize();}// 自定义Strategypublic static void setContextHolderStrategy(SecurityContextHolderStrategy strategy) {Assert.notNull(strategy, "securityContextHolderStrategy cannot be null");SecurityContextHolder.strategyName = MODE_PRE_INITIALIZED;SecurityContextHolder.strategy = strategy;initialize();}public static SecurityContext getContext() {return strategy.getContext();}public static void setContext(SecurityContext context) {strategy.setContext(context);}public static void clearContext() {strategy.clearContext();}

可以看到,SecurityContextHolder实际上是一个门面,具体的Context存储在SecurityContextHolderStrategy中,来看看该接口默认的实现 ThreadLocalSecurityContextHolderStrategy :

final class ThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy {// ThreadLocalprivate static final ThreadLocal<SecurityContext> contextHolder = new ThreadLocal<>();@Overridepublic void clearContext() {contextHolder.remove();}@Overridepublic SecurityContext getContext() {SecurityContext ctx = contextHolder.get();if (ctx == null) {ctx = createEmptyContext();contextHolder.set(ctx);}return ctx;}@Overridepublic void setContext(SecurityContext context) {Assert.notNull(context, "Only non-null SecurityContext instances are permitted");contextHolder.set(context);}@Overridepublic SecurityContext createEmptyContext() {return new SecurityContextImpl();}}

AuthenticationManager

public interface AuthenticationManager {// 传入一个待认证的Authentication// 返回 a fully authenticated object including credentialsAuthentication authenticate(Authentication authentication) throws AuthenticationException;}

AuthenticationManager的最常用实现类 ProviderManager,ProviderManager调用多个AuthenticationProvider来认证传入的Authentication,只要有一个认证成功即可返回(返回nonNull),否则会抛出异常,AuthenticationManager默认支持三种异常:

public class ProviderManager implements AuthenticationManager, MessageSourceAware, InitializingBean {// 事件发布,默认空实现private AuthenticationEventPublisher eventPublisher = new NullEventPublisher();// 实际认证的AuthenticationProviderprivate List<AuthenticationProvider> providers = Collections.emptyList();// 父级认证Managerprivate AuthenticationManager parent;@Overridepublic Authentication authenticate(Authentication authentication) throws AuthenticationException {for (AuthenticationProvider provider : getProviders()) {if (!provider.supports(toTest)) {continue;}...result = provider.authenticate(authentication);if (result != null) {copyDetails(authentication, result);break;}...}// 该类中AuthenticationManager都判断完了,结果还是空,调用parent开始认证if (result == null && this.parent != null) {// Allow the parent to try.parentResult = this.parent.authenticate(authentication);}...// AbstractAuthenticationToken就是Authentication接口的实现类,模板模式// 常用的UsernamePasswordAuthenticationToken和OAuth3AuthenticationToken都extends这个Abstract类private void copyDetails(Authentication source, Authentication dest) {if ((dest instanceof AbstractAuthenticationToken) && (dest.getDetails() == null)) {AbstractAuthenticationToken token = (AbstractAuthenticationToken) dest;token.setDetails(source.getDetails());}}}

可以看到 ProviderManager implements AuthenticationManager将认证工作进一步分配给 AuthenticationProvider,而这个AuthenticationProvider会根据支持的认证方式来认证,所以这个接口除了认证方法还有一个是否支持认证的判断方法:

public interface AuthenticationProvider {Authentication authenticate(Authentication authentication) throws AuthenticationException;boolean supports(Class<?> authentication);

AuthenticationProvider常见的实现类有:

以上就是关于“Spring Security认证机制是什么”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯