Spring Security本质上是一连串的Filter, 然后又以一个独立的Filter的形式插入到Filter Chain里,其名为FilterChainProxy。 如图所示。

实际上FilterChainProxy下面可以有多条Filter Chain,来针对不同的URL做验证,而Filter Chain中所拥有的Filter则会根据定义的服务自动增减。所以无需要显示再定义这些Filter,除非想要实现自己的逻辑。

关键类

Authentication

Authentication是一个接口,用来表示用户认证信息,在用户登录认证之前相关信息会封装为一个Authentication具体实现类的对象,在登录认证成功之后又会生成一个信息更全面,包含用户权限等信息的Authentication对象,然后把它保存在 SecurityContextHolder所持有的SecurityContext中,供后续的程序进行调用,如访问权限的鉴定等。

AuthenticationManager

用来做验证的最主要的接口为AuthenticationManager,这个接口只有一个方法:

public interface AuthenticationManager {

  Authentication authenticate(Authentication authentication)
throws AuthenticationException; }

其中authenticate()方法运行后可能会有三种情况:

  1. 验证成功,返回一个带有用户信息的Authentication
  2. 验证失败,抛出一个AuthenticationException异常。
  3. 无法判断,返回null

ProviderManager

ProviderManager是上面的AuthenticationManager最常见的实现,它不自己处理验证,而是将验证委托给其所配置的AuthenticationProvider列表,然后会依次调用每一个 AuthenticationProvider进行认证,这个过程中只要有一个AuthenticationProvider验证成功,就不会再继续做更多验证,会直接以该认证结果作为ProviderManager的认证结果。

认证过程

  1. 用户使用用户名和密码进行登录。
  2. Spring Security将获取到的用户名和密码封装成一个Authentication接口的实现类,比如常用的UsernamePasswordAuthenticationToken
  3. 将上述产生的Authentication对象传递给AuthenticationManager的实现类ProviderManager进行认证。
  4. ProviderManager依次调用各个AuthenticationProvider进行认证,认证成功后返回一个封装了用户权限等信息的Authentication对象。
  5. AuthenticationManager返回的Authentication对象赋予给当前的SecurityContext

自定义验证

有了以上的知识储备后就可以来自定义验证方法了。通过上面可以看出,实际上真正来做验证操作的是一个个的AuthenticationProvider,所以如果要自定义验证方法,只需要实现一个自己的AuthenticationProvider然后再将其添加进ProviderManager里就行了。

自定义AuthenticationProvider

@Component
public class CustomAuthenticationProvider
implements AuthenticationProvider { @Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException { String name = authentication.getName();
String password = authentication.getCredentials().toString(); if (shouldAuthenticateAgainstThirdPartySystem()) { // use the credentials
// and authenticate against the third-party system
return new UsernamePasswordAuthenticationToken(
name, password, new ArrayList<>());
} else {
return null;
}
} @Override
public boolean supports(Class<?> authentication) {
return authentication.equals(
UsernamePasswordAuthenticationToken.class);
}
}

其中的supports()方法接受一个authentication参数,用来判断传进来的authentication是不是该AuthenticationProvider能够处理的类型。

注册AuthenticationProvider

现在再将刚创建的AuthenticationProvider与ProviderManager里注册,所有操作就完成了。

@Configuration
@EnableWebSecurity
@ComponentScan("org.baeldung.security")
public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired
private CustomAuthenticationProvider authProvider; @Override
protected void configure(
AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(authProvider);
} @Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic();
}
}

参考资料

  1. Spring Security Architecture
  2. Spring Security Authentication Provider
  3. Spring Security 简介系列

Spring Security验证流程剖析及自定义验证方法的更多相关文章

  1. Spring Security入门(2-3)Spring Security 的运行原理 4 - 自定义登录方法和页面

    参考链接,多谢作者: http://blog.csdn.net/lee353086/article/details/52586916 http元素下的form-login元素是用来定义表单登录信息的. ...

  2. spring boot集成mybatis-plus插件进行自定义sql方法开发时报nested exception is org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):

    spring boot集成mybatis-plus插件进行自定义sql方法开发时报nested exception is org.apache.ibatis.binding.BindingExcept ...

  3. Spring Security框架下Restful Token的验证方案

    项目使用Restful的规范,权限内容的访问,考虑使用Token验证的权限解决方案. 验证方案(简要概括): 首先,用户需要登陆,成功登陆后返回一个Token串: 然后用户访问有权限的内容时需要上传T ...

  4. spring security使用hibernate进行查询数据库验证

    前面查询数据库采用的都是jdbc方式,如果系统使用的是hibernate,该如何进行呢,下面就是实现步骤,关键还是实现自定义的UserDetailsService 项目结构如下: 使用hibernat ...

  5. Spring Security OAuth2之resource_id配置与验证

    一.resource_id的作用 Spring Security OAuth2 架构上分为Authorization Server认证服务器和Resource Server资源服务器.我们可以为每一个 ...

  6. Spring Security认证流程分析--练气后期

    写在前面 在前一篇文章中,我们介绍了如何配置spring security的自定义认证页面,以及前后端分离场景下如何获取spring security的CSRF Token.在这一篇文章中我们将来分析 ...

  7. Spring Security OAuth2 微服务认证中心自定义授权模式扩展以及常见登录认证场景下的应用实战

    一. 前言 [APP 移动端]Spring Security OAuth2 手机短信验证码模式 [微信小程序]Spring Security OAuth2 微信授权模式 [管理系统]Spring Se ...

  8. 03 spring security执行流程分析

    spring security主要是依赖一系列的Filter来实现权限验证的,责任链设计模式是跑不了的.下面简单记录一下spring操作这些Filter的过程. 1. WebSecurityConfi ...

  9. 【权限管理】Spring Security 执行流程

    转自:https://blog.csdn.net/weixin_37689658/article/details/92752890 1.基本配置使用 (1)创建配置类 创建一个配置类SecurityC ...

随机推荐

  1. Spring源码情操陶冶-自定义节点的解析

    本文承接前文Spring源码情操陶冶-DefaultBeanDefinitionDocumentReader#parseBeanDefinitions,特开辟出一块新地来啃啃这块有意思的骨头 自定义节 ...

  2. 小甲鱼OD学习第11讲

    这次我们的任务是破解这个需要注册的软件,如下图所示 我们这次从字符串入手,我们查找 unregistered  字符串 然后我们在如下图的字符串下断点 然后我们来到断点处,我们观察到 地址为 0040 ...

  3. coredump故障分析

    如果一个程序运行3天后才会出错,这个时候 难道需要我们一直用GDB调试程序3天吗? 这个时候我们就需要使用到core  dump: 1.Core Dump又叫核心转存.当程序在运行过程中发生异常, 这 ...

  4. ACE-6.1.0 linux 下的编译与安装步骤

    ACE-6.1.0 linux 下的编译与安装步骤  引用至http://www.cnblogs.com/liangxiaxu/archive/2013/03/07/2948417.html 1.从  ...

  5. SSE图像算法优化系列十六:经典USM锐化中的分支判断语句SSE实现的几种方法尝试。

    分支判断的语句一般来说是不太适合进行SSE优化的,因为他会破坏代码的并行性,但是也不是所有的都是这样的,在合适的场景中运用SSE还是能对分支预测进行一定的优化的,我们这里以某一个算法的部分代码为例进行 ...

  6. PH日期格式化

    %M 月名字(January--December) %W 星期名字(Sunday--Saturday) %D 有英语前缀的月份的日期(1st, 2nd, 3rd, 等等.) %Y 年, 数字, 4 位 ...

  7. Linux 编译安装 php 扩展包 curl

    php源码目录:/root/php php编译目录:/usr/local/webserver/php/ curl源码目录:/root/curl 1.curl,主要用于发送http请求,是php的一个扩 ...

  8. 利用while语句,条件为输入的字符不为'\n'.

    题目:输入一行字符,分别统计出其中英文字母.空格.数字和其它字符的个数. 1.程序分析:利用while语句,条件为输入的字符不为'\n'. 一个很简单的问题,其实换种方式就能完成,但是我就想怎么着才能 ...

  9. Java经典编程题50道之四十六

    编程实现两个字符串的连接. public class Example46 {    public static void main(String[] args) {        addString( ...

  10. HTML5-svg圆形饼状图进度条实现原理

    <svg width="440" height="440" viewbox="0 0 440 440"> <circle ...