1. Spring Security自定义拦截器
HttpSecurity实际上就是在配置Spring security的过滤器链,比如:CSRF,CORS,表单登录等,每个配置器对应一个过滤器,可以通过HttpSecurity配置过滤器的行为。
甚至可以像CRSF一样直接关闭过滤器,例如:SessionManagement
Spring Security通过SessionManagermentConfigurer来配置SessionManagerment的行为,与SessionManagermentConfigurer类似的配置器还有CorsConfigurer,RememberMeConfigurer等,他们都实现了SecurityConfigurer的标准接口。
SessionManagementConfigurer是在configure方法中将最终的SessionManagementFilter插入过滤器链来实现会话管理的。
除了Spring security提供的过滤器外,我们还可以添加自己的过滤器以实现更多的功能,这些都是可以在HttpSecurity中实现
虽然Spring Security 的过滤器链对过滤器没有特殊要求,只要继承了Filter即可,但是在Spring体系中,推荐使用OnePerRequestFilter来实现,它可以确保一次请求只会通过一次该过滤器(Filter实际并不能保证这一点)
其实关于这个自定义Filter,我个人感觉有个比较danteng的地方,比如:我们在实现图片验证码或者一些其他的登录相关的验证码的时候,我们可能会做到在账号跟密码验证了之后对这个验证码进行验证,然后我就必须有个这种操作: http.addFilterBefore(filter,.class); 因为如果验证码验证错误,我们就不需要也没必要再往后验证了,所以我们得知道我们定义的这个验证码过滤器得在什么时候验证在哪个过滤器之前或者之后验证,那么问题来了,或许我们并不知道Spring Security给我们提供了哪些或者什么样的过滤器,我们得去记住这些过滤器,这就有点不友好了。在HttpSecurityBuilder接口中,有一段这样的注释:
非常爽眼~
2. Spring Security源码(一):认证、授权、过滤器链
因为看了很多博客,发现很多人的使用风格都不一样,有点懵。感觉最好的方法就是多看一些源码,然后自己选择想要的使用方式。
spring security版本:2.1.6.RELEASE
这里先讲这三种的关系
AuthenticationManager、ProviderManager、AuthenticationProvider
封装了用户身份信息
一个接口,只有一个方法
ProviderManager是AuthenticationManager的实现类,提供了基本认证实现逻辑和流程;
先看这个方法这个方法,是 用来认证 的方法
关键点
AuthenticationProvider 本身也就是一个 接口 ,它有实现类 和的 子类DaoAuthenticationProvider
只有 两个 方法
总结
这是一个抽象类,是 模板模 式。定义好了认证流程,我们去实现流程中的一些 环节 方法。达到了 自定义认证 的效果
的子类,实现了一些 抽象方法
retrieveUser
主要就是用 UserDetailsService 去查找用户
createSuccessAuthentication
本质还是调用了父类的方法,就是新建了一个Authentication,然后将 UserDetails 的 信息 传递过去
UserDetailsService是一个接口,提供了一个方法
感觉这个接口没什么用,就是用来管理用户类的
SS在http后台中起作用主要是基于 Servlet Filters 的,我们先来看看什么是 Filter 是如何作用在 Servlet 中的。
springSecurityFilterChain 是个接口 , DefaultSecurityFilterChain 是它的实现类,而DefaultSecurityFilterChain 内部存在这一个 Filters 列表 ,关于SS中的过滤器和他们的执行顺序(Order)可以查看 官方文档 ,当我们需要自定义Filter的时候就会用到。 当请求到来时,在 ss 里边的 Filter就会作用请求,如下图 :
在上面我们说到了SS有 自己的一条过滤器链 ,下面就是截图:(执行顺序就是集合中的顺序)
下面说一下几个 比较重要的 Filter 的 处理逻辑
整个调用流程是,先调用其父类 .doFilter() 方法,然后再执行 .attemptAuthentication() 方法进行验证;
父类是 (又是模板模式,子类实现抽象方法,父类定好流程)
requiresAuthentication
判断是否需要当前filter处理,就是判断路径、请求方法等等
以的构造方法为例
successfulAuthentication
这里的认证就是 第一节的内容 ( this.getAuthenticationManager().authenticate(authRequest) )
从上图中过滤器的执行顺序图中可以看出 AnonymousAuthenticationFilter 过滤器是在 等过滤器之后 ,如果它前面的过滤器 都没有认证成功 ,Spring Security则为当前的SecurityContextHolder中添加一个Authenticaiton 的匿名实现类 AnonymousAuthenticationToken;
总结
ExceptionTranslationFilter 异常处理过滤器,该过滤器用来处理在系统 证授权过程 中抛出的异常(也就是下一个过滤器FilterSecurityInterceptor),主要是 处理 AuthenticationException 和 AccessDeniedException 。
此过滤器为认证授权过滤器链中 最后一个过滤器 ,该过滤器之后就是请求真正的 /xx服务
Spring Security默认使用 AffirmativeBased 实现 AccessDecisionManager 的 decide 方法来实现授权
到此位置 authentication 当前用户信息,fl当前访问的 资源路径及attributes当前资源路径的决策 (即是否需要认证)。剩下就是 判断 当前用户的角色Authentication.authorites 是否权限 访问决策访问当前资源fi
Spring Security 核心过滤器链分析
3. SpringCloud Gateway-添加cookies的过滤器
@Component
public class CookiesFilter implements Ordered, GlobalFilter {
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest().mutate().headers((httpHeaders) -> {
String csrf =new HttpCookie("csrf", "3838a26d-07f7-11e9-b5f7").toString();
String ssn =new HttpCookie("ssn", "MTU0NT").toString();
httpHeaders.set("Cookie", csrf+";"+ssn);
}).build();
return chain.filter(exchange.mutate().request(request).build());
}
@Override
public int getOrder() {
return -100;
}
}
4. SpringBoot系列:4.session和鉴权—过滤器和拦截器
本文主要介绍下,SpringBoot的web项目中,
使用redis保存并共享session,可以实现集群内的登录信息共享。SpringBoot项目中,通过在 application.yml 增加redis的配置,即可实现对session的存储和修改。
那么session是在何时被处理的?session的key又是如何生成的呢?这里实际使用了web项目中的过滤器。
在SpringBoot的web项目中,启动的tomcat在处理http请求时,有一个很重要的类: ApplicationFilterChain 。每个http请求在处理时都会通过这个类。这个类负责按顺序处理全部已注册的 Filter ,也就是过滤器。通过实现tomcat中的 Filter 接口,就可以定义一个过滤器。
在SpringBoot中的web项目中,有几个默认的过滤器,其中一个就是用来处理session的: SessionRepositoryFilter
SessionRepositoryFilter 主要的成员是两个接口,都有多个可选的实现类,通过这两个成员就实现了对session的解析。
当然也可以实现一个自己的过滤器,主要有两种方式:
下面我们使用第一种方式实现一个限制指定IP的过滤器:
通过过滤器解析session后,就可以根据session中保存的内容,判断当前登录的用户权限。
这里是通过一个拦截器实现的,在拦截器中可以直接通过 HttpServletRequest.getSession() 方法直接获取session的信息。
一个简单的拦截器实现如下:
定义之后要注册到处理流程中:
先来看下过滤器和拦截器的执行顺序,通过debug得到的执行顺序如下图:
在大部分场景中,过滤器和拦截器都是可互换的,使用哪个都可以。
过滤器和拦截器也有些区别,这里不谈实现和规范的差异,就说下使用中可能涉及的区别:
最后对于过滤器和拦截器的应用场景,说下个人的总结。基于执行顺序,方法参数和SpringBoot中的一些实现类来看。
以上内容属个人学习总结,如有不当之处,欢迎在评论中指正