背景
作者在进行新版的Springboot3.2.5+SpringSecurity6的整合过程中,需要对Jwt的功能进行测试。根据网上的建议,采用token方式进行鉴权的项目,就不要对请求采取csrf保护了。
错误的做法
于是就采用原来的写法如下:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().antMatchers("/no-csrf/**");
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf()
.ignoringAntMatchers("/no-csrf/**") // 忽略这些路径
.and()
// 其他配置...
;
return http.build();
}
}
结果是无效,甚至系统直接报错指出不建议以上写法。
更错误的做法
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable() // 直接关闭所有保护
.and()
// 其他配置...
;
return http.build();
}
}
先说这个做法起不到关闭部分请求保护的作用,而是直接全部关闭了CSRF保护。如果同一个项目中即有web内容也有api内容,无法起到分别配置安全设置的效果。而且,以上写法最新版并不支持。
解决方案一
以下写法是新版本的正确写法,也不知道老外为什么那么喜欢折腾,往往有些功能没有什么本质上的变化,只是写法各有千秋。
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf
.requireCsrfProtectionMatcher((request) -> !request.getRequestURI().startsWith("/api/")))
// 其他配置...
;
return http.build();
}
}
以方法虽然可以解除请求api的csrf保护,但是也会导致web项目出现没有权限的问题,这肯定不是我们想要的结果。
解决方案二
http
// .csrf(AbstractHttpConfigurer::disable) //直接全部关闭,这不是我们想要的结果。
.csrf(csrf->csrf
.ignoringRequestMatchers(new RequestMatcher() {
@Override
public boolean matches(HttpServletRequest request) {
String path = request.getRequestURI();
return !path.matches("/api/");
}
}))
//其它配置
这个方法确实达到了我们想要的结果,web模块和api模块的鉴权都得到了保障,这样我们就可以在同一个项目里即可实现web功能也可以实现api功能。
结论
以上写法仅对Springboot3.2.5+SpringSecurity6.2.4这个版本有效,其它的版本没测,请读者注意。这种写法看起来确实简洁了不少,一个http解决所有的配置问题,也能精准控制访问配置。