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. 吴恩达深度学习笔记(deeplearning.ai)之卷积神经网络(二)

    经典网络 LeNet-5 AlexNet VGG Ng介绍了上述三个在计算机视觉中的经典网络.网络深度逐渐增加,训练的参数数量也骤增.AlexNet大约6000万参数,VGG大约上亿参数. 从中我们可 ...

  2. 51NOD 1237 最大公约数之和 V3 [杜教筛]

    1237 最大公约数之和 V3 题意:求\(\sum_{i=1}^n\sum_{j=1}^n(i,j)\) 令\(A(n)=\sum_{i=1}^n(n,i) = \sum_{d\mid n}d \c ...

  3. BZOJ 2839: 集合计数 [容斥原理 组合]

    2839: 集合计数 题意:n个元素的集合,选出若干子集使得交集大小为k,求方案数 先选出k个\(\binom{n}{k}\),剩下选出一些集合交集为空集 考虑容斥 \[ 交集为\emptyset = ...

  4. 解决asp.net MVC中 当前上下文中不存在名称“model” 的问题

    在vs2013下打开同事上传的cshtml视图文件报错,出现当前上下文中不存在名称“model”,ViewBag,Url等等,在视图中也没有智能提示了:但是不影响编译运行,只是开发时候比较麻烦,但在同 ...

  5. cnpm,vue等命令不识别的问题废人解决方案

    关于安装的cnpm,vue等不识别的问题 我想了很久然后再网上看了一些教程发现添加系统变量Path没什么用 我就在用户变量里面添加的,完美解决问题 在我的电脑右键->属性->高级系统设置- ...

  6. 计算机基础之Windows10操作系统安装U盘制作

    1.第一步,下载Windows10--ISO镜像(Windows7类似),下载站点: https://msdn.itellyou.cn/(百度搜索msdn即可),个人认为这是最干净的操作系统镜像站点, ...

  7. ES6标准入门 第一章:简介

    ECMAScript 6 是JavaScript 语言的下一代标准:发布于2015年,又称为ECMAScript 2015. ECMAScript 与 JavaScript 的关系:前者是后者的规范, ...

  8. php + 和 array_merge的区别

    (1)对于+,当key相同时,都是舍弃后面的结果: array_merge ,当key相同时,key是字符,则后面的覆盖前面的:key是数字,则不发生覆盖,会重新建立数组索引. $arr1 = arr ...

  9. angularjs 指令详解

    一.指令定义 对于指令,可以把它简单的理解成在特定DOM元素上运行的函数,指令可以扩展这个元素的功能. 首先来看个完整的参数示例再来详细的介绍各个参数的作用及用法: <div my-direct ...

  10. sql必知必会笔记

    1.DISTINCT 用于剔除重复的值, 如果后跟多个列, 则要求所有列的值都相同才会被剔除.    SELECT DISTINCT ven_id, prod_price FROM Products; ...