Spring Security修炼手册(二)————Security的认证流程

    那么经过第一节的介绍,你们对于Security认证的使用应该具有了一个基本的认识,那么这节主要有三个知识点。一、初步的带你们了解Security中几个过滤器(后面会一点点的加入其它过滤器)。二、表单认证的处理流程。三、如何自定义用户认证逻辑。那么废话很少说,直接进入第一点。前端

    哦!对了,我还要补充一点,有不少小伙伴私信我说,怎么能在用户完成认证以后,转跳到上一次请求的页面,个人回答是:So Easy!别配置defaultSuccessUrl就好了。java

1、Spring Security中的过滤器

    经过第一节的介绍,你们应该知道Security是基于过滤器链的,那么它都有哪些过滤器?而且都是作什么的呢?下面一张图,为你们介绍几个初级的过滤器。算法

    那么spring security就是由这样一个过滤器链组成,在spring boot启动的时候被加载其中,每一个过滤器负责校验不一样的信息,最后的FilterSecurityIntercept是在前面的过滤器都校验经过的时候读取你对security的配置信息,好比是否为VIP才能访问等等,而后会抛出相应的异常,异常会被ExceptionTranslationFilter捕获,而后将不一样异常对应的结果返回给前端。spring

    过滤器链上绿色的是能够经过配置来决定它生不生效,蓝色和黄色的是必定会执行,且必须按此顺序执行,开发人员不可更改的。在补充一下,别看蓝色的以Intercept结尾,可是他真的是一个过滤器,不是拦截器。数据库

   经过名字你们能够看出来两个绿色的过滤器一个是用户名密码认证过滤器,一个叫基本认证过滤器,那么当咱们使用表单进行认证的时候,就是在usernamePasswordAuthticationFilter中进行处理的,咱们先简单看一眼这个类中的代码:ide

2、表单认证的流程

    下面咱们经过DeBug看一下,在输入用户名密码,点击登陆后,在后台代码中到底发生了什么。首先咱们在以下四个类中打上断点: UsernamePasswordAuthenticationFilter、ExceptionTranslationFilter、FilterSecurityIntercept、和咱们的controller。工具

ExceptionTranslationFilter断点说明:加密

FilterSecurityInterceptor断点说明:spa

    打好断点后,咱们执行登陆操做。code

    能够看到在在UsernamePasswordAuthenticationFilter中获取到了表单的用户名密码信息。而Security中提供了一个接口叫作UserDetailsService,这个接口很是简单只有一个方法,传进来的参数就是当前认证请求的用户名,返回值叫作UserDetails接口,这个UserDetails实则定义了当前用户的一些状态,如基本信息、是否可用、密码是否过时等等,那么由于咱们如今尚未去具体的实现,因此都是走的Security默认的实现,后面咱们会有本身的实现,在这里对比用户名密码OK后则经过第一步认证,而后走到FilterSecurityInterceptor,上一小节的图片中有介绍这个类中有一个对比配置的方法,那么咱们先走进这个方法内,能够看到实则对咱们要访问的URL进行了一次认证。

当咱们有权限访问此URL时,则会执行咱们的Controller

认证流程结束。

3、自定义认证逻辑

    在第二小节咱们介绍了认证流程中用户名密码的对比等是在一个叫UserDetailsService的接口中实现,而  咱们在第一章经过YML配置了一个内存用户,那么很明显,这样的方式并知足不了咱们的业务需求,咱们通常都是要把用户名密码权限这些信息放到数据库中,下面我来详细的介绍。

    咱们先看一看UserDetailServer中的代码:

这个接口中只有一个方法,参数username就是表单中的用户名,咱们能够经过用户名进行CURD的操做,返回值UserDetails一样也是一个接口,里面定义了用户名,密码,密码是否过时,帐户是否可用等一系列的属性。

接下来咱们具体实现一下:

@Component
public class MyUserDetailsServer implements UserDetailsService {

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		// TODO Auto-generated method stub
		
		return new User(username, "$2a$10$ofPkBDUezOJp6Sik63Q/0.QlU8a1itEyzldjSXqfn2nDPqXjN0Ljm", AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
	}

}

这个返回对象User是security给咱们的默认实现,第一个参数就是传过来的用户名,第二个参数是经过用户名进行再数据库中查询到的密码(省略了数据库操做),第三个参数是从数据库中查询出来的当前用户拥有的权限(省略了数据库操做,直接使用工具类生成),因为我使用了加密密码,因此在SecurityConfig中须要将加密算法注入,代码以下:

若是想使用其余加密算法,实现PasswordEncoder接口便可。

这时候咱们重启项目,用户名能够任意,密码为,123456a(上面密文对应的原文),这时候个人系统就拥有了自定义认证的功能。

相关文章
相关标签/搜索