看一看Spring Security 原理分析
作者:互联网
引言
在试题系统开发过程中,认证方式越来越完善,也对Spring Security有了更加深刻的理解。
本文,我们一起来领略Spring Security的设计原理。
原理
必备基础
Servlet是Java Web领域中的软件开发规范,Tomcat是实现Servlet规范的Java Web服务器。
package javax.servlet;
public interface Servlet {
public void init(ServletConfig config) throws ServletException;
public ServletConfig getServletConfig();
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
public String getServletInfo();
public void destroy();
}
Servlet长这样,生命周期十分简单,初始化init、业务逻辑service、销毁destroy。
简单来说:我们根据Servlet接口开发我们的应用,服务器开发商根据Servlet接口开发Servlet服务器。
前端HTTP请求,Tomcat选择路由匹配的Servlet,如果已经实例化,直接调用service;如果未实例化,实例化后调用service,处理完之后返回响应。
图中示例的url统一采用小写,关于url大小写的问题,以下是结论,虽然有些url是大小写不敏感的,但是这使得表示唯一性变得困难,我们通常应该认为大小写是敏感的。
There may be URLs, or parts of URLs, where case doesn’t matter, but identifying these may not be easy. Users should always consider that URLs are case-sensitive.
为了在Servlet前后执行其他逻辑,定义了Filter接口,在请求前后都会执行。
原理分析
从Spring Security官方文档摘抄的一张图:
Spring Security的原理其实就是通过Servlet中的Filter技术进行实现的,通过一系列内置的或自定义的安全Filter,实现接口认证与授权。
Spring Security官方也给出了默认Filter的执行顺序,先执行认证的过滤器,后执行授权的过滤器,其中就有我们常用的UsernamePasswordAuthenticationFilter、BasicAuthenticationFilter等等。
阅读源码一个Filter源码即可理解整个认证架构设计。
注:以下代码中部分无关代码已被删减。
public class BasicAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain chain) {
try {
/** 从请求中获取用户名密码信息 */
UsernamePasswordAuthenticationToken authRequest = authenticationConverter.convert(request);
/** 如果没有相关信息,说明不是此种认证方式,执行后续过滤器 */
if (authRequest == null) {
chain.doFilter(request, response);
return;
}
/** 获取用户名 */
String username = authRequest.getName();
/** 判断该用户是否需要认证 */
if (authenticationIsRequired(username)) {
/** 尝试使用 token 进行认证 */
Authentication authResult = this.authenticationManager
.authenticate(authRequest);
/** 认证成功,将认证结果置入上下文 */
SecurityContextHolder.getContext().setAuthentication(authResult);
/** 认证成功相关回调 */
this.rememberMeServices.loginSuccess(request, response, authResult);
onSuccessfulAuthentication(request, response, authResult);
}
}
catch (AuthenticationException failed) {
/** 认证失败,清空当前上下文信息 */
SecurityContextHolder.clearContext();
/** 认证失败相关回调 */
this.rememberMeServices.loginFail(request, response);
onUnsuccessfulAuthentication(request, response, failed);
/** 如果需要忽略失败,则继续执行后续过滤器 */
if (this.ignoreFailure) {
chain.doFilter(request, response);
}
/** 否则开始执行新的认证方案 */
else {
this.authenticationEntryPoint.commence(request, response, failed);
}
return;
}
/** 本过滤器执行完毕,执行后续过滤器 */
chain.doFilter(request, response);
}
}
其实很简单是不是?
添加自定义认证逻辑
如果默认的验证方式不满足要求,要怎么添加自定义验证方式呢?其实只需要添加自定义的Filter即可。
就比如说常见的短信验证码登录方式:
默认不支持短信方式,我们可以在过滤器链中植入一个自定义的短信验证过滤器,认证成功后设置认证信息即可。
上面都是自己整理好的!我就把资料贡献出来给有需要的人!顺便求一波关注。学习我们是认真的,拿大厂offer是势在必得的。想了解点击一下java交流群哦
[java交流群](想了解更多点一下哦)
SecurityContextHolder.getContext().setAuthentication(authResult);
Reactive
这个是上个月遇到的问题,尝试了一下OAuth 2.0认证架构。
其实这个架构很普遍,许多项目都采用该种架构。只不过都是采用Spring Cloud Netflix Zuul + Spring Security Resource Server的实现。
这里我尝试将Zuul换成Spring Cloud Gateway,因为Zuul的阻塞IO在网关层面实在太影响性能了。
前面已经说了,Spring Security中的认证与授权方式是通过Servlet技术套装中的Filter实现的,Tomcat提供了Servlet的运行环境。
Spring Cloud Netflix Zuul集成Spring Boot Starter Web也就是默认的Tomcat实现网关,所以Zuul中是有Servlet的运行环境的。
而非阻塞的Spring Cloud Gateway基于Spring WebFlux框架,不支持Servlet,底层采用高性能的Netty服务器。
Spring WebFlux与Spring MVC的对比请看下图:
所以当Spring Security与Spring Cloud Gateway集成时,就会出错,Spring Security需要的Servlet环境没有被满足。
这也是之前对Reactive的理解不到位而引起的错误,WebFlux环境下,应该集成Spring Security Reactive,而非默认的Spring Security。
总结
经资料查阅,高性能的 Netty十分受各大互联网企业欢迎,Twitter、Facebook、苹果、微博都在使用Netty,具体Netty为什么更适合高并发?以后我们一起学习。
最后
上面都是自己整理好的!我就把资料贡献出来给有需要的人!顺便求一波关注。学习我们是认真的,拿大厂offer是势在必得的。想了解点击一下java交流群哦
[java交流群](想了解更多点一下哦)
原文链接:https://segmentfault.com/a/1190000021941111
标签:Spring,看一看,request,认证,Security,Servlet,response 来源: https://blog.csdn.net/TIANTIAN_ZZ/article/details/104752507