gpt4 book ai didi

java - 如何仅针对特定 url 额外添加 Spring Security 验证码过滤器

转载 作者:IT老高 更新时间:2023-10-28 13:47:10 30 4
gpt4 key购买 nike

我正在寻找一种非侵入性的方式来为某些 api 调用添加验证码过滤器。

我的设置由两个 WebSecurityConfigurerAdapters 组成,每个都有一个过滤器(不是验证码过滤器):

  • 内部 api(“/iapi”在所有调用中使用过滤器 A,但也会忽略一些 public 请求,例如/authenticate)
  • 外部 api(“/eapi”在所有调用中使用过滤器 B)

如何在公共(public)、内部 api 或外部 api 调用中添加过滤器之前 Spring Security 的东西?我不需要SecurityContext,只需要检查请求 header 中的验证码,转发到filterChain(普通过滤器)或手动拒绝访问。我尝试在 web.xml 中声明一个过滤器,但这破坏了使用依赖注入(inject)的能力。

这是我的 Spring 安全配置:

@EnableWebSecurity
public class SpringSecurityConfig {
@Configuration
@Order(1)
@EnableGlobalMethodSecurity(securedEnabled = true)
public static class InternalApiConfigurerAdapter extends WebSecurityConfigurerAdapter {

@Autowired
private Filter filterA;

public InternalApiConfigurerAdapter() {
super(true);
}

@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/public/**");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/iapi/**")
.exceptionHandling().and()
.anonymous().and()
.servletApi().and()
.authorizeRequests()
.anyRequest().authenticated().and()
.addFilterBefore(filterA, (Class<? extends Filter>) UsernamePasswordAuthenticationFilter.class);
}

@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return authenticationManager();
}
}

@Configuration
@Order(2)
@EnableGlobalMethodSecurity(securedEnabled = true)
public static class ExternalApiConfigurerAdapter extends WebSecurityConfigurerAdapter {

@Autowired
private FilterB filterB;

public ExternalApiConfigurerAdapter() {
super(true);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/external/**")
.exceptionHandling().and()
.anonymous().and()
.servletApi().and()
.authorizeRequests()
.anyRequest().authenticated().and()
.addFilterBefore(filterB, (Class<? extends Filter>) UsernamePasswordAuthenticationFilter.class);
}

@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return authenticationManager();
}
}

更新:目前我有一个在 web.xml 中声明的过滤器的工作配置。但是,它有与 Spring 上下文分离的缺点(例如,没有 Autowiring bean),所以我正在寻找一个更好的利用 Spring 的解决方案。

总结:还有两个问题:

  1. 仅为特定的 url 添加过滤器 - 在任何配置中使用 beforeFilter(...) 会为该配置的所有 url 添加过滤器。 Antmatchers没有工作。我需要类似的东西:/iapi/captcha/、/external/captcha/、/public/captcha/*。
  2. 我有一个完全绕过 Spring Security 的公共(public) api:(web .ignoring() .antMatchers("/public/**");)。我需要绕过 Spring Security 但仍在那里声明一个过滤器,使用 Spring Autowiring 但不一定是 Spring Security 功能,因为我的验证码过滤器仅以无状态方式拒绝或转发调用。

最佳答案

您已经有一个在 UsernamePasswordAuthenticationFilter 之前插入过滤器 A 和 B 的工作配置,因此应该很容易添加另一个自定义过滤器。

首先,您创建过滤器,并将其声明为 bean,或者使用 @Component 注释类,或者作为 @Bean 内的 @ Configuration 类,因此可以使用 @Autowired 进行注入(inject)。

现在您可以将它作为过滤器 A 和 B 注入(inject)并使用它。根据Filter Ordering在 Spring Security 引用文档部分,链中的第一个过滤器是 ChannelProcessingFilter,因此为了在 Spring Security 过滤器链中的任何其他内容之前插入过滤器,您可以这样做:

@Autowired
private CaptchaFilter captchaFilter;

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/iapi/**")
.addFilterBefore(captchaFilter, (Class<? extends Filter>) ChannelProcessingFilter.class)
.addFilterBefore(filterA, (Class<? extends Filter>) UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.anyRequest().authenticated();
}

顺便说一下,exceptionHandling() anonymous()servletApi() 是不需要的,因为在扩展 WebSecurityConfigurerAdapter,除了 anonymous() 当您实际指定更多配置详细信息时,这些都已包含在内,因为它指出 HttpSecurity javadoc

请记住,Spring Security “入口点”,DelegatingFilterProxy 仍将在您的过滤器之前执行,但该组件仅将请求委托(delegate)给链中的第一个过滤器,在这种情况下将是 CaptchaFilter,因此您确实会在 Spring Security 的任何其他操作之前执行您的过滤器。

但是如果你仍然希望验证码过滤器在DelegatingFilterProxy之前执行,在Spring Security配置中是没有办法的,需要在web.xml中声明。 xml 文件。


更新:如果您不想在其他配置中包含验证码过滤器,您可以随时添加第三个配置,配置类如下:

@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SpringSecurityConfig {

@Configuration
@Order(1)
public static class CaptchaApiConfigurerAdatper extends WebSecurityConfigurerAdapter {

@Autowired
private CaptchaFilter captchaFilter;

public CaptchaApiConfigurerAdatper() {
super(true);
}

@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/public/**");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatcher("/iapi/captcha**")
.antMatcher("/external/captcha**")
.and()
.addFilterBefore(captchaFilter, (Class<? extends Filter>) ChannelProcessingFilter.class)
.authorizeRequests()
.anyRequest().authenticated();
}
}

@Configuration
@Order(2)
public static class InternalApiConfigurerAdapter extends WebSecurityConfigurerAdapter {

// ommiting code for the sake of clarity
}

@Configuration
@Order(3)
public static class ExternalApiConfigurerAdapter extends WebSecurityConfigurerAdapter {

// ommiting code for the sake of clarity
}

对了,另外一个小技巧,你可以将特定配置之外的所有通用配置重构到主类中,比如@EnableGlobalMethodSecurity(securedEnabled = true) AuthenticationManager,WebSecurity 为公众跳过安全性,但对于那些因为主类没有扩展任何东西的人,你应该 @Autowire 方法声明。

虽然 WebSecurity 会有一个问题,但如果您忽略 /public/**HttpSecurity 的匹配器 /public/captcha** 将被忽略,所以我想,您不应该重构 WebSecurity 并在 CaptchaConfig 类中使用不同的模式,因此它不会重叠。

关于java - 如何仅针对特定 url 额外添加 Spring Security 验证码过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34314084/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com