我正在寻找一种非侵入性的方法来为某些api调用添加验证码过滤器。
我的设置包含两个WebSecurityConfigurerAdapters
,每个都有一个过滤器(不是验证码过滤器):
如何在公共,内部api或外部api调用上添加过滤器之前之前的内容?我不需要SecurityContext,只需要检查请求头中的Captcha,转发到filterChain(普通过滤器)或手动拒绝访问。我尝试在web.xml中声明一个过滤器,但这会破坏使用依赖注入的能力。
这是我的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 Context分离(例如没有bean的自动装配),因此我正在寻找一种利用Spring的更好的解决方案。
摘要:还有两个问题:
答案 0 :(得分:6)
您已经有一个工作配置,在UsernamePasswordAuthenticationFilter
之前插入了过滤器A和B,因此应该很容易添加另一个自定义过滤器。
首先,创建过滤器,并将其声明为bean,使用@Component
注释该类,或者在@Bean
类中注释为@Configuration
,因此它已准备好注入@Autowired
。
现在您可以将其作为过滤器A和B注入,并使用它。根据Spring Security参考文档中的Filter Ordering部分,链中的第一个Filter是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
仍然会在过滤器之前执行,但是这个组件只将请求委托给链中的第一个过滤器,在这种情况下,它将是CaptchaFilter,所以你真的会在Spring Security之前执行你的过滤器。
但是如果您仍然希望在DelegatingFilterProxy
之前执行验证码过滤器,则无法在Spring Security配置中执行此操作,您需要在web.xml
文件中声明它。 / p>
更新:如果您不希望在其他配置中包含验证码过滤器,您可以随时添加第三个配置,配置类如下:
@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类中使用不同的模式,因此它不会重叠。