我正在寻找一种非侵入性的方法来为某些api调用添加验证码过滤器.
我的设置包括两个WebSecurityConfigurerAdapters
,每个都有一个过滤器(不是验证码过滤器):
内部api("/ iapi"在所有呼叫上使用过滤器A,但也忽略一些公共请求,如/ authenticate)
外部api("/ eapi"在所有呼叫中使用过滤器B)
如何在Spring Security内容,公共内部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的更好的解决方案.
摘要:还有两个问题:
仅为特定URL添加过滤器- 在任何配置中使用beforeFilter(...)会向该配置的所有URL添加过滤器.Antmatchers没有工作.我需要这样的东西:/ iapi/captcha/,/ external/captcha /,/ public/captcha/*.
我有一个完全绕过Spring Security的公共API :( web .ignoring().antMatchers("/ public/**");).我需要绕过Spring Security,但仍使用Spring自动装配声明过滤器,但不一定是Spring Security功能,因为我的验证码过滤器只能以无状态方式拒绝或转发呼叫.
saljuama.. 7
您已经有一个工作配置,之前插入了过滤器A和B,UsernamePasswordAuthenticationFilter
因此应该很容易添加另一个自定义过滤器.
首先,创建过滤器,并将其声明为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
文件中声明它.
更新:如果您不希望在其他配置中包含验证码过滤器,您可以随时添加第三个配置,配置类如下:
@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类不同的模式,以便它不重叠.
您已经有一个工作配置,之前插入了过滤器A和B,UsernamePasswordAuthenticationFilter
因此应该很容易添加另一个自定义过滤器.
首先,创建过滤器,并将其声明为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
文件中声明它.
更新:如果您不希望在其他配置中包含验证码过滤器,您可以随时添加第三个配置,配置类如下:
@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类不同的模式,以便它不重叠.