pyhton=实现调用自定义模块_(九)自定义认证流程

通过前面的文章介绍,我们对于SpringSecurity的运行原理已经有了一个基本的掌握。所以现在就来在框架默认功能的基础之上自定义我们的功能。

一、思考

如果想自定义一个认证流程,我们需要哪些模块?稍微想一下就可以得出答案:

1、登录信息验证

2、会话管理

3、授权

4、注销

SpringSecurity独特的SecurityBuilder和SecurityConfigurer结构,使得模块与模块之间既能够独立工作,又能够组合发挥。SecurityConfigurer的init方法,可以将不同模块的变量进行共享,从而影响到configurer阶段对于SecurityBuilder的属性设置,以至于最终影响到框架运行结果。

我们来一步步的定义我们自己的框架流程:

二、如何自定义SpringSecurity的配置

前面的文章中我们提到过,SpringSecurity框架的springSecurityFilterChain,其主要工作是交给SecurityFilterChain来完成的。创建springSecurityFilterChain的SecurityBuilder为WebSecurity,创建SecurityFilterChain的SecurityBuilder为HttpSecurity。而与WebSecurity的SecurityConfigurer在框架中只提供了一个默认的实现:

c83038e295e3cc6bbed11f3601c5af73.png

但是从代码中我们可以发现,Spring上下文中可以同时存在多个WebSecurityConfigurerAdapter,但只有@Order最大的那个会生效,并且Order是唯一的。如果不指定Order则默认为Integer.MAX_VALUE,也就说我们只需要定义一个不带@Order注解的WebSecurityAdapter注册到spring容器中就能替换掉SpringSecurity提供的DefaultConfigurerAdapter,来修改WebSecurity的行为,通过WebSecurity来创建我们自定义的springSecurityFilterChain

85683e0bb94feb5649f70ddad927536a.png

但是真正起作用的其实是SecurityFilterChain对象,所以自定义WebSecurityConfigurerAdapter的主要目的其实是为了自定义SecurityFilterChain的构造器——HttpSecurity。

54cd22c8bfaef5596d807255e1b22aea.png

3446a34e31cc25c6daeb4de816987002.png
getHttp方法

032cfb781f37d236cd7a794276a6329d.png
configurer方法

WebSecurityConfigurerAdapter中涉及到HttpSecurity的主要是getHttp方法和configure方法。从代码中来看,如果我们想只应用SpringSecurity提供的骨架,而自定义请求认证的流程,第一步是要把HttpSecurity对象所有的SecurityConfigurer都取消掉,然后选择我们需要的进行设置。

所以我们可以进行两处修改:

1、disableDefaults属性设置为true

2、重写configurer方法

f16384a24675ad31fa66f84e28da3bee.png

现在我们的配置类是这个样子了。我们只保留了请求拦截,登陆,请求缓存,会话管理,注销,对于所有请求需要登录认证这几个功能。至于配置的顺序,我们并不需要去关心,因为框架中已经事先定义好了所有的filter的顺序,在build的时候其会进行排序:

1b48a8f17ca705e1a54f8e93e239ec78.png

三、自定义AuthenticationProvider

前面的源码分析文章中,我们已经知道登陆是交给UsernamePasswordAuthenticationFilter来做的,而具体的细节又是交给AuthenticationManager做的。SpringSecurity默认给我们提供的AuthenticationManager是ProviderManager,而且其工作原理之前也已经介绍了,本篇是实战篇,所以不涉及过多的原理。HttpSecurity中的AuthenticationManager是从HttpSecurity中获取的

db1458fb0d52f28154625de15f1d8b2a.png

所以要想自定义AuthenticationManager还得从HttpSecurity对象入手,即前面提到的WebSecurityConfigurerAdapter的getHttp方法。

701c494faab7712395adb1059f8595f0.png

前面的文章中已经分析过这段代码,这里简单的讲下。由于disableLocalConfigureAuthenticationBldr属性默认为true,即使用框架默认的AuthenticationManager:

a74d3ee17236b48c60fd2420b7629202.png

系统默认的AuthenticationManager是由全局的AuthenticationManagerBuilder——authBuilder结合globalAuthConfigurers配置类创建的。所以我们要想自定义全局的AuthenticationManager,首先要清楚globalAuthConfigurers为全局的AuthenticationManagerBuilder做了哪些支持:

globalAuthConfigurers主要的功能就是提供了加载Provider到AuthenticationManager中:

1、第一个AuthenticationProvider默认加载的是spring上下文中的第一个bean,如果不存在则为null

d753bffecba29503caf13af3d580b16f.png

2、如果第一个Provider不存在,则会使用spring上下文中userDetailsService创建了一个DaoAuthenticationProvider

c7110f0ba89722d888ff7bd89bae682d.png

ba91e922206916a05b4f7afdd3e06096.png

对于AuthenticationManager的验证流程我们也已经分析过了,他会依次调用其所有的provider,只要有一个验证成功就说明登录成功。而且从Spring中加载的AuthenticationProvider作为第一个,很明显就是留给我们的钩子,所以我们只需要在Spring上下文中创建一个我们自己的Provider,就能自动被SpringSecurity框架所加载,这样SpringSecurity就不会创建默认的Provider了

e293c831acd9049f9539d3cfb2e4a826.png

通过debug可以看到我们自定义的provider确实应用到框架里了。

c648c1f699e758358a0a4e5d09fac7ec.png

同样的道理,如果我们不自定义AuthenticationProvider,转而自定义UserDetailsService,也一样可以实现我们的目的。不过为了方便我们还是自定义Provider。

四、自定义登陆成功和失败处理器

既然有登录,那就肯定有登录成功和登录失败的情况,我们可以统称为登录事件。SpringSecurity作为一个成熟的框架,肯定不会连这么简单的功能都遗漏掉。登陆成功会调用SuccessHandler的onAuthenticationSuccess方法,登陆失败会调用FailedHandler的onAuthenticationFailure方法,系统默认提供的handler是SimpleUrlAuthenticationFailureHandler和MyLoginSuccessHandler。但是我们可能要做自己的定制化操作,比如记录用户登录时间,登录失败原因等,所以要自定义handler:

42217e0e0ff40d06fe52dae4e42da2f6.png

545afdf4781841a6c9bb00198b47743e.png

继承SimpleUrlAuthenticationFailureHandlerSimpleUrlAuthenticationSuccessHandler即可,并且标记为bean,然后在自定义的配置文件中引入,设置到登录模块中去。

同样的,注销之后我们可能也要处理注销的事件,所以可以继承LogoutSuccessHandler构造我们自己的处理器

0c0121d56a3e9232cbd3ed63dc83fc96.png

定义好之后直接在自定义的MyWebSecurityConfigurerAdapter配置类中将其注入到登录和注销的configure里面即可。

09a850be3e150089e8af9aaabf9a4d41.png

最后的authorizeRequests().anyRequest().authenticated()表示对于所有的请求,都需要"authenticated"授权,即要求所有的请求访问都需要进行登录认证,但登录页面除外,默认的登录页面具有"permit all"权限,即对所有请求开放。具体的权限配置,还是放到下一篇来讲,因为和认证相同,授权也是一个很复杂的过程。

以上我们就配置好了一个SpringBoot + SpringSecurity项目的基本骨架,应该说是十分的简单,现在来回顾一下我们配置了哪些东西,然后还需要哪些东西:

1、自定义了AuthenticationProvider,并且标记为bean

2、自定义了三个handler,loginSuccessHandler,loginFailedHandler,logoutSuccessHandler

3、继承WebSecurityConfigurerAdapter,自定义了SpringSecurity的配置类。

c710bf3e44cbdfb3911c3729df396705.png

是不是很简单。只需要这么简单的几个类,我们就算是初步接入了SpringSecurity框架,并且具备了认证的能力。不过这也仅仅是有了认证的能力,具体的认证细节,事件处理细节还需要我们自己去按照自己的业务去自己写。

这里没有去写AuthenticationProvider的authenticate方法的具体细节的原因主要是:

认证授权虽然是两个部分但是他们的功能会有部分重合,所以在定义认证结果之前,还得先看授权的细节。所以下面一篇文章就来一起看下授权的细节,以及我们如何去根据认证的结果来控制权限

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值