我正在寻找一种非侵入式的方法,为特定的 API 调用添加验证码过滤器。
我的设置由两个 WebSecurityConfigurerAdapter
组成,每个都有一个过滤器(不是验证码过滤器):
- 内部 API("/iapi" 对所有调用使用过滤器 A,但也忽略一些公共请求,如 /authenticate)
- 外部 API("/eapi" 对所有调用使用过滤器 B)
我该如何在 Spring Security 之前为公共、内部 API 或外部 API 调用添加过滤器?我不需要 SecurityContext,只需要检查请求标头中是否存在验证码,然后转发到 filterChain(正常过滤器),或手动拒绝访问。我尝试在 web.xml 中声明过滤器,但这会破坏使用依赖注入的能力。
这是我的 Spring Security 配置:
@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上下文分离(例如,没有bean自动连接),因此我正在寻找一种更好的解决方案来利用Spring。总结:仍存在两个问题:
- 仅为特定网址添加过滤器-在任何配置内使用beforeFilter(...)都会向该配置的所有网址添加过滤器。Antmatchers无法正常工作。我需要像这样的东西:/iapi/captcha/、 /external/captcha/ 、/public/captcha/*。
- 我有一个公共API完全绕过Spring Security:(web .ignoring() .antMatchers("/public/**");)。我需要绕过Spring Security,但仍然在那里声明一个过滤器,使用Spring自动连接,但不一定是Spring Security功能,因为我的验证码过滤器仅以无状态方式拒绝或转发调用。
Filter A
和Filter B
。它们是你验证码过滤器的占位符,还是你已经有了真正的实现?如果是这样,请相应地更新你的问题。 - ksokol.addFilterBefore()
将过滤器插入到想要的位置。 - saljuama