当前位置: 首页 > news >正文

Spring Security

Spring Security

  spring提供的安全框架。主要提供了认证和授权的功能。简单梳理看看。
  原理简单说就是Spring Security在基于Servlet应用中,其底层采用了Filter机制实现了对请求的认证,授权和漏洞防御等功能。

DelegatingFilterProxy

  我们知道,Filter是Servlet规范里面的东西。基于Servlet规范,我们可以为ServletR勇气注入一些自定义Filters。
  但是在Spring应用中,实现了Filter接口的Bean无法被Servlet容器感知到。因此,Spring提供了一个DelegatingFilterProxy代理类,DelegatingFilterProxy实现了Filter,因此它可以被注入到FilterChain中,同时,当请求到来时,它会把请求转发到Spring容器中实现了Filter接口的Bean实体。也就是说,DelegatingFilterProxy桥接了Servlet容器和Spring容器。
  默认情况下,DelegatingFilterProxy从Spring容器中获取得到的就是FilterChainProxy实体,而FilterChainProxy也是一个代理类,它最终会将请求转发到SpringSecurity提供的SecurityFilterChain中。
  FilterChainProxy就是Spring Security真正的入口起始点。调试代码的时候,可以将断点设置在FilterChainProxy#doFilter就可以追踪SpringSecurity完整调用流程。

FilterChainProxy

public class FilterChainProxy extends GenericFilterBean {
//FILTER_APPLIED 变量是一个标记,用来标记过滤器是否已经执行过了private static final String FILTER_APPLIED = FilterChainProxy.class.getName().concat(".APPLIED");
//filterChains 是过滤器链,注意,这个是过滤器链,而不是一个个的过滤器private List<SecurityFilterChain> filterChains;
//filterChainValidator 是 FilterChainProxy 配置完成后的校验方法,默认使用的 NullFilterChainValidator 实际上对应了一个空方法,也就是不做任何校验private FilterChainValidator filterChainValidator = new NullFilterChainValidator();//FilterChain为servlet的过滤器链@Override
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {//为true,表示尚未执行过;false表示,已经标记boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;if (clearContext) {try {request.setAttribute(FILTER_APPLIED, Boolean.TRUE);//执行spring security的过滤器doFilterInternal(request, response, chain);}finally {//清除SecurityContextHolder 中保存的用户信息,同时移除 request 中的标记SecurityContextHolder.clearContext();request.removeAttribute(FILTER_APPLIED);}}else {doFilterInternal(request, response, chain);}
}

  在 doFilter 方法中,正常来说,clearContext 参数每次都是 true,于是每次都先给 request 标记上 FILTER_APPLIED 属性,然后执行 doFilterInternal 方法去走过滤器,执行完毕后,最后在 finally 代码块中清除 SecurityContextHolder 中保存的用户信息,同时移除 request 中的标记。

private void doFilterInternal(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {FirewalledRequest fwRequest = firewall.getFirewalledRequest((HttpServletRequest) request);HttpServletResponse fwResponse = firewall.getFirewalledResponse((HttpServletResponse) response);//根据当前request,从FilterChainProxy中配置的多个过滤器链(可以只有一个),找到和当前相匹配的一个securityFilterChain,并获取filtersList<Filter> filters = getFilters(fwRequest);if (filters == null || filters.size() == 0) {if (logger.isDebugEnabled()) {logger.debug(UrlUtils.buildRequestUrl(fwRequest)+ (filters == null ? " has no matching filters": " has an empty filter list"));}fwRequest.reset();//如果filters为null,表示当前请求不需要执行security的过滤器链,直接执行servlet上的过滤器链chain.doFilter(fwRequest, fwResponse);return;}//如果需要执行security的过滤器链,首先构造一个虚拟的过滤器链VirtualFilterChain vfc = new VirtualFilterChain(fwRequest, chain, filters);vfc.doFilter(fwRequest, fwResponse);
}//request匹配到的过滤器链上的所有filters
private List<Filter> getFilters(HttpServletRequest request) {for (SecurityFilterChain chain : filterChains) {if (chain.matches(request)) {return chain.getFilters();}}return null;
}

  doFilterInternal 方法就比较重要了:

  1. 首先将请求封装为一个 FirewalledRequest 对象,在这个封装的过程中,也会判断请求是否合法。
  2. 对响应进行封装。
  3. 调用 getFilters 方法找到过滤器链。该方法就是根据当前的请求,从 filterChains 中找到对应的过滤器链,然后由该过滤器链去处理请求。
  4. 如果找出来的 filters 为 null,或者集合中没有元素,那就是说明当前请求不需要经过过滤器。直接执行 chain.doFilter ,这个就又回到原生过滤器中去了。那么什么时候会发生这种情况呢?那就是针对项目中的静态资源,如果我们配置了资源放行,如 web.ignoring().antMatchers(“/hello”);,那么当你请求 /hello 接口时就会走到这里来,也就是说这个不经过 Spring Security Filter。
  5. 如果查
http://www.lryc.cn/news/359670.html

相关文章:

  • vue中大屏可视化适配所有屏幕大小
  • AI大模型探索之路-实战篇12: 构建互动式Agent智能数据分析平台:实现多轮对话控制
  • 深入理解文件系统和日志分析
  • vue+vant移动端显示table表格加横向滚动条
  • webserver服务器从零搭建到上线(八)|EpollPoller事件分发器类
  • SD-WAN:企业网络转型的必然趋势
  • 构建高效稳定的短视频直播系统架构
  • python分别保存聚类分析结果+KeyError: ‘CustomerID‘报错
  • Sui与Atoma合作为开发者提供AI支持
  • go-gin中session实现redis前缀和db库选择+单点登录
  • python-双胞胎字符串
  • 万字长文,小白新手怎么开始做YOLO实验,从零开始教!整体思路在这里,科研指南针!
  • MDR-1A用什么前端:深度解析与实用指南
  • 01Linux以及操作系统概述
  • 华为OD刷题C卷 - 每日刷题 1
  • 基于ELK的日志管理【开发实践】
  • 音视频开发—音频相关概念:数模转换、PCM数据与WAV文件详解
  • Elasticsearch 8.1官网文档梳理 - 十三、Search your data(数据搜索)
  • 笔墨挥毫如游龙 最是经典铁线篆——记著名书法家王子彬
  • 智慧校园有哪些特征
  • day25回溯算法part02| 216.组合总和III 17.电话号码的字母组合
  • AWS联网和内容分发服务
  • vscode设置编辑器文件自动保存
  • SJ705C安全帽高温预处理箱
  • AI盒子在智慧加油站的应用
  • IC开发——VCS基本用法
  • MongoDB~存储引擎了解
  • JavaScript实现粒子数字倒计时效果附完整注释
  • Dubbo SPI(Service Provider Interface)机制深度解析
  • 常用中间件各版本下载