温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何分析Spring Security中过滤器链的配置问题

发布时间:2021-12-02 15:57:14 阅读:363 作者:柒染 栏目:大数据
开发者测试专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

如何分析Spring Security中过滤器链的配置问题,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

首先这个问题本身是有点问题的,因为 http.authorizeRequests() 并非总是第一个,虽然大部分情况下,我们看到的是第一个,但是也有很多情况 http.authorizeRequests() 不是首先出现。要搞明白这个问题,我们就要搞清楚 http.authorizeRequests() 到底是啥意思!

这就涉及到 Spring Security 中过滤器链的配置问题

 

1.从过滤器开始

即使大家没有仔细研究过 Spring Security 中认证、授权功能的实现机制,大概也都多多少少听说过 Spring Security 这些功能是通过过滤器来实现的。

是的,没错!Spring Security 中一共提供了 32 个过滤器,其中默认使用的有 15 个,这些过滤器松哥在以后的文章中再和大家细说,今天我们就先来看看过滤器的配置问题。

在一个 Web 项目中,请求流程大概如下图所示:

如何分析Spring Security中过滤器链的配置问题  

请求从客户端发起(例如浏览器),然后穿过层层 Filter,最终来到 Servlet 上,被 Servlet 所处理。

那有小伙伴要问了,Spring Security 中默认的 15 个过滤器就是这样嵌套在 Client 和 Servlet 之间吗?

不是的!

上图中的 Filter 我们可以称之为 Web Filter,Spring Security 中的 Filter 我们可以称之为 Security Filter,它们之间的关系如下图:

如何分析Spring Security中过滤器链的配置问题  

可以看到,Spring Security Filter 并不是直接嵌入到 Web Filter 中的,而是通过 FilterChainProxy 来统一管理 Spring Security Filter,FilterChainProxy 本身则通过 Spring 提供的 DelegatingFilterProxy 代理过滤器嵌入到 Web Filter 之中。

❝  

DelegatingFilterProxy 很多小伙伴应该比较熟悉,在 Spring 中手工整合 Spring Session、Shiro 等工具时都离不开它,现在用了 Spring Boot,很多事情 Spring Boot 帮我们做了,所以有时候会感觉 DelegatingFilterProxy 的存在感有所降低,实际上它一直都在。

 

2.多个过滤器链

上面和大家介绍的是单个过滤器链,实际上,在 Spring Security 中,可能存在多个过滤器链。

在松哥前面讲 OAuth3 系列的时候,有涉及到多个过滤器链,但是一直没有拎出来单独讲过,今天就来和大家分享一下。

有人会问,下面这种配置是不是就是多个过滤器链?

@Overrideprotected void configure(HttpSecurity http) throws Exception {    http.authorizeRequests()            .antMatchers("/admin/**").hasRole("admin")            .antMatchers("/user/**").hasRole("user")            .anyRequest().authenticated()            ...            .csrf().disable();}
 

这样的配置相信大家都见过,但是这并不是多个过滤器链,这是一个过滤器链。因为不管是 /admin/** 还是 /user/** ,走过的过滤器都是一样的,只是不同的路径判断条件不一样而已。

如果系统存在多个过滤器链,多个过滤器链会在 FilterChainProxy 中进行划分,如下图:

如何分析Spring Security中过滤器链的配置问题  

可以看到,当请求到达 FilterChainProxy 之后,FilterChainProxy 会根据请求的路径,将请求转发到不同的 Spring Security Filters 上面去,不同的 Spring Security Filters 对应了不同的过滤器,也就是不同的请求将经过不同的过滤器。

正常情况下,我们配置的都是一个过滤器链,多个过滤器链怎么配置呢?松哥给大家一个举一个简单的例子:

@Configurationpublic class SecurityConfig {    @Bean    protected UserDetailsService userDetailsService() {        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();        manager.createUser(User.withUsername("javaboy").password("{bcrypt}$2a$10$Sb1gAUH4wwazfNiqflKZve4Ubh.spJcxgHG8Cp29DeGya5zsHENqi").roles("admin""aaa""bbb").build());        manager.createUser(User.withUsername("sang").password("{noop}123").roles("admin").build());        manager.createUser(User.withUsername("江南一点雨").password("{MD5}{Wucj/L8wMTMzFi3oBKWsETNeXbMFaHZW9vCK9mahMHc=}4d43db282b36d7f0421498fdc693f2a2").roles("user""aaa""bbb").build());        return manager;    }    @Configuration    @Order(1)    static class DefaultWebSecurityConfig extends WebSecurityConfigurerAdapter {        @Override        protected void configure(HttpSecurity http) throws Exception {            http.antMatcher("/foo/**")                    .authorizeRequests()                    .anyRequest().hasRole("admin")                    .and()                    .csrf().disable();        }    }    @Configuration    @Order(2)    static class DefaultWebSecurityConfig2 extends WebSecurityConfigurerAdapter {        @Override        protected void configure(HttpSecurity http) throws Exception {            http.antMatcher("/bar/**")                    .authorizeRequests()                    .anyRequest().hasRole("user")                    .and()                    .formLogin()                    .permitAll()                    .and()                    .csrf().disable();        }    }}
 
  1. 首先,SecurityConfig 不再需要继承自 WebSecurityConfigurerAdapter 了,只是作为一个普通的配置类,加上 @Configuration 注解即可。
  2. 提供 UserDetailsService 实例,相当于是我们的数据源。
  3. 创建静态内部类继承 WebSecurityConfigurerAdapter 类,同时用 @Configuration 注解标记静态内部类是一个配置类,配置类里边的代码就和之前的一样了,无需赘述。
  4. 每一个静态内部类相当于就是一个过滤器链的配置。
  5. 注意在静态内部类里边,我没有使用     http.authorizeRequests() 开始,     http.authorizeRequests() 配置表示该过滤器链过滤的路径是     /**。在静态内部类里边,我是用了     http.antMatcher("/bar/**") 开启配置,表示将当前过滤器链的拦截范围限定在     /bar/**
  6. 当存在多个过滤器链的时候,必然会有一个优先级的问题,所以每一个过滤器链的配置类上通过 @Order(2) 注解来标记优先级。

从上面这段代码中大家可以看到,configure(HttpSecurity http) 方法似乎就是在配置过滤器链?是的没错!我们在该方法中的配置,都是在添加/移除/修改 Spring Security 默认提供的过滤器,所以该方法就是在配置 Spring Security 中的过滤器链,至于是怎么配置的,松哥以后抽时间再来和大家细说。

 

3.回到问题

最后,我们在回到一开始小伙伴提的问题。

首先,http.authorizeRequests() 配置并非总在第一行出现,如果只有一个过滤器链,他总是在第一行出现,表示该过滤器链的拦截规则是 /**请求只有先被过滤器链拦截下来,接下来才会进入到不同的 Security Filters 中进行处理),如果存在多个过滤器链,就不一定了。

仅仅从字面意思来理解,authorizeRequests() 方法的返回值是 ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry,ExpressionUrlAuthorizationConfigurer 可以为多组不同的 RequestMatcher 配置不同的权限规则,就是大家看到的 .antMatchers("/admin/**").hasRole("admin").antMatchers("/user/**").hasRole("user")

看完上述内容,你们掌握如何分析Spring Security中过滤器链的配置问题的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注亿速云行业资讯频道,感谢各位的阅读!

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

原文链接:https://my.oschina.net/u/3669799/blog/4393850

AI

开发者交流群×