spring security 源码分析

表单登录

UsernamePasswordAuthenticationFilter

/login Post 请求

会被这个过滤器拦截

 

《spring security 源码分析》

如果为/login时 会经过

if (!this.requiresAuthentication(request, response))

判断是否和设置的loginProcessingUrl一致

《spring security 源码分析》

《spring security 源码分析》

此时 由相应的AuthenticationProvider(这里是DaoAuthenticationProvider)匹配Authentication,如果support()

可以自定义provider给ProviderManager:

在webconfig中重写

     @Override
     protected AuthenticationManager authenticationManager() throws Exception {
         ProviderManager authenticationManager = new   ProviderManager(Arrays.asList(inMemoryAuthenticationProvider,daoAuthenticationProvider()));
         //不擦除认证密码,擦除会导致TokenBasedRememberMeServices因为找不到Credentials再调用UserDetailsService而抛出       UsernameNotFoundException
         authenticationManager.setEraseCredentialsAfterAuthentication(false);
         return authenticationManager;
     }

《spring security 源码分析》

《spring security 源码分析》

AbstractUserDetailsAuthenticationProvider 内置了缓存机制,从缓存中获取不到的 UserDetails 信息的话,就调用如下方法获取用户信息,然后和 用户传来的信息进行对比来判断是否验证成功。

验证:provider.authenticate(authentication),进入retrieveUser()

《spring security 源码分析》

开始调用

UserDetailsService().loadUserByUsername(username);

根据username查出整个user 

和之前的authentication

调用 this.additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken)authentication);

验证成功后

《spring security 源码分析》

然后通过

this.getRedirectStrategy().sendRedirect(request, response, targetUrl);

重定向,故在此进入filter

《spring security 源码分析》

整个最基本的流程图:

《spring security 源码分析》

 

spring security 加密 ,这里使用

BCryptPasswordEncoder

BCryptPasswordEncoder 使用BCrypt的强散列哈希加密实现,并可以由客户端指定加密的强度strength,强度越高安全性自然就越高,默认为10.

特点:每一次hash都自动生成不同的盐,并将盐值放在hash值中

《spring security 源码分析》

 

security 核心——-过滤器链

 

  • SecurityContextPersistenceFilter: 整个Spring Security 过滤器链的开端,它有两个作用:一是当请求到来时,检查Session中是否存在SecurityContext,如果不存在,就创建一个新的SecurityContext。二是请求结束时将SecurityContext放入 Session中,并清空 SecurityContextHolder
  • UsernamePasswordAuthenticationFilter: 继承自抽象类 AbstractAuthenticationProcessingFilter,当进行表单登录时,该Filter将用户名和密码封装成一个 UsernamePasswordAuthentication进行验证。
  • AnonymousAuthenticationFilter: 匿名身份过滤器,当前面的Filter认证后依然没有用户信息时,该Filter会生成一个匿名身份——AnonymousAuthenticationToken。一般的作用是用于匿名登录。
  • ExceptionTranslationFilter: 异常转换过滤器,用于处理 FilterSecurityInterceptor抛出的异常。
  • FilterSecurityInterceptor: 过滤器链最后的关卡,从 SecurityContextHolder中获取 Authentication,比对用户拥有的权限和所访问资源需要的权限。

 

《spring security 源码分析》

SecurityContextPersistenceFilter

请求先经过 SecurityContextPersistenceFilter 过滤器,在前面就曾提到,该Filter有两个作用,其中之一就是在请求到来时,创建 SecurityContext安全上下文,我们来看看它内部是如何做的,部分源码如下:

《spring security 源码分析》

我们这里是第一次请求,读取的安全上下文中是没有 Authentication身份信息的,将安全上下文设置到 SecurityContextHolder之后,进入下一个过滤器。

UsernamePasswordAuthenticationFilter

经过 SecurityContextPersistenceFilter过滤器后来到 UsernamePasswordAuthenticationFilter过滤器,因为我们假定的是第一次请求,所以 SecurityContext并没有包含认证过的 Authentication从此过滤器开始的操作对于表单登录来说是非常关键的,包含了表单登录的核心认证步骤

UsernamePasswordAuthenticationFilter 的父类是 AbstractAuthenticationProcessingFilter,首先进入父类的 foFilter方法

《spring security 源码分析》

具体都在跟上面说的一样

AnonymousAuthenticationFilter

匿名认证过滤器,它主要是针对匿名登录,如果前面的Filter,比如UsernamePasswordAuthenticationFilter执行完毕后,SecurityContext依旧没有用户信息,那么AnonymousAuthenticationFilter才会起作用,生成一个匿名身份信息——AnonymousAuthenticationToken

《spring security 源码分析》

ExceptionTranslationFilter

ExceptionTranslationFilter 简单的说就是处理 FilterSecurityInterceptor 抛出的异常,其内部doFilter方法源码如下:

《spring security 源码分析》

FilterSecurityInterceptor

FilterSecurityInterceptor 过滤器是最后的关卡,之前的请求最终会来到这里,它的大致工作流程就是

  • 封装请求信息
  • 从系统中读取配信息,即资源所需的权限信息
  • SecurityContextHolder中获取之前认证过的 Authentication对象,即表示当前用户所拥有的权限
  • 然后根据上面获取到的三种信息,传入一个权限校验器中,对于当前请求来说,比对用户拥有的权限和资源所需的权限。若比对成功,则进入真正系统的请求处理逻辑,反之,会抛出相应的异常

《spring security 源码分析》

 

使用第三方登录(github登录)

加入过滤器

IntegrationAuthenticationFilter(自己写的)

当符合/oauth/github时,不执行chain.doFileter,直接重定向

下面是spring security的源码 也是类似的处理方式

《spring security 源码分析》

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/Jesse_cool/article/details/82593163
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞