Java 为具有特定请求头的请求切换Spring安全性
我正在尝试切换/绕过/禁用Spring Security(身份验证和授权),以所有具有特定请求头的请求 例如,如果使用该请求头命中请求url,则应绕过Spring安全性,否则不应绕过它 为此,我使用以下requestMatchers Spring安全配置:Java 为具有特定请求头的请求切换Spring安全性,java,spring,spring-boot,spring-security,Java,Spring,Spring Boot,Spring Security,我正在尝试切换/绕过/禁用Spring Security(身份验证和授权),以所有具有特定请求头的请求 例如,如果使用该请求头命中请求url,则应绕过Spring安全性,否则不应绕过它 为此,我使用以下requestMatchers Spring安全配置: @Override public void configure(WebSecurity web) throws Exception { web.ignoring() .antMatchers(HttpMethod.
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(HttpMethod.GET)
.antMatchers(HttpMethod.OPTIONS)
.requestMatchers(new RequestHeaderRequestMatcher("TEST-HEADER","TEST-VALUE"));
}
我剩下的安全配置是:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity (prePostEnabled = true)
@ConditionalOnProperty (name = "security.enabled", havingValue = "true", matchIfMissing = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private SecurityProps securityProps;
@Autowired
private MyUserDetailsService myUserDetailsService;
@Autowired
private MyAuthenticationEntryPoint myAuthenticationEntryPoint;
@Autowired
private MyCORSFilter myCORSFilter;
public SecurityConfig() {
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable()
.addFilterBefore(myCORSFilter, SessionManagementFilter.class)
.addFilterBefore(requestHeaderFilter(), RequestHeaderAuthenticationFilter.class)
.authenticationProvider(preauthAuthProvider())
.authorizeRequests()
.antMatchers(HttpMethod.GET, securityProps.getNoAuthGetPattern()).permitAll()
.antMatchers(HttpMethod.OPTIONS, securityProps.getNoAuthOptionsPattern()).permitAll()
.requestMatchers(new RequestHeaderRequestMatcher("TEST-HEADER","TEST-VALUE")).permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(myAuthenticationEntryPoint);
}
@Autowired
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(preauthAuthProvider());
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(HttpMethod.GET)
.antMatchers(HttpMethod.OPTIONS)
.requestMatchers(new RequestHeaderRequestMatcher("TEST-HEADER","TEST-VALUE"));
}
public RequestHeaderAuthenticationFilter requestHeaderFilter() throws Exception {
RequestHeaderAuthenticationFilter requestHeaderAuthenticationFilter = new RequestHeaderAuthenticationFilter();
requestHeaderAuthenticationFilter.setPrincipalRequestHeader(MySecurityConstants.LOGIN_HEADER);
requestHeaderAuthenticationFilter.setAuthenticationManager(authenticationManager());
requestHeaderAuthenticationFilter.setExceptionIfHeaderMissing(false);
requestHeaderAuthenticationFilter.setAuthenticationFailureHandler(new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
if (exception instanceof MySecurityException) {
myAuthenticationEntryPoint.commenceMySecurityException(request, response, (MySecurityException) exception);
} else if (exception instanceof UsernameNotFoundException) {
myAuthenticationEntryPoint.commenceUsernameNotFoundException(request, response,
(UsernameNotFoundException) exception);
} else if (exception instanceof PreAuthenticatedCredentialsNotFoundException) {
myAuthenticationEntryPoint.commence(request, response, exception);
}
}
});
return requestHeaderAuthenticationFilter;
}
@Bean
public PreAuthenticatedAuthenticationProvider preauthAuthProvider() throws Exception {
PreAuthenticatedAuthenticationProvider authProvider = new PreAuthenticatedAuthenticationProvider();
authProvider.setPreAuthenticatedUserDetailsService(userDetailsServiceWrapper());
return authProvider;
}
@Bean
public UserDetailsByNameServiceWrapper<PreAuthenticatedAuthenticationToken> userDetailsServiceWrapper()
throws Exception {
UserDetailsByNameServiceWrapper<PreAuthenticatedAuthenticationToken> wrapper =
new UserDetailsByNameServiceWrapper<>();
wrapper.setUserDetailsService(ivyUserDetailsService);
return wrapper;
}
}
谁能帮我找出我做错了什么?我的方法正确吗,或者我需要做些别的事情来实现这一点
编辑:
我在
beforeInvocation()
方法中的org.springframework.security.access.intercept.AbstractSecurityInterceptor
类中遇到此异常,它试图从SecurityContextHolder获取身份验证对象AbstractSecurityInterceptor
由其子类MethodSecurityInterceptor
调用,该子类是从我的Spring控制器调用的,该控制器带有@PreAuthorize
注释。我认为您的旁路运行良好。它跳过了支票
安全的授权检查部分从SecurityContext获取经过身份验证的对象,该对象将在请求通过spring安全过滤器时设置。
因此,当您跳过安全过滤器时,还未设置SecurityContext,因此会出现错误
您可以这样做,为您的自定义页眉大小写手动设置它
try {
SecurityContext ctx = SecurityContextHolder.createEmptyContext();
SecurityContextHolder.setContext(ctx);
ctx.setAuthentication(event.getAuthentication());
} finally {
SecurityContextHolder.clearContext();
}
编辑1:
回答所有的问题
但如果是这样的话,那么我想所有的GET call也应该有
失败,但我的GET呼叫工作正常
由于您添加了这条线路,所有GET呼叫都将从安全检查中跳过
.antMatchers(HttpMethod.GET, securityProps.getNoAuthGetPattern()).permitAll()
我可以在哪里添加您提到的代码?任何特定的过滤器或
其他地方
我在过滤器里做过类似的事情。
提及
查看答案中的TokenAuthenticationFilter
类。其中我手动设置
注意:它的JWT实现,但很好参考
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (tokenHelper.validateToken(authToken, userDetails)) {
// create authentication
TokenBasedAuthentication authentication = new TokenBasedAuthentication(userDetails);
authentication.setToken(authToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
你的答案是什么
我刚从一些答案中得到这个案例,现在找不到它的链接。但是您可以像这样或像上面那样设置身份验证
Authentication authentication = new PreAuthenticatedAuthenticationToken("system", null);
authentication.setAuthenticated(true);
context.setAuthentication(authentication);
谢谢你的回答。但如果是这样的话,我想所有的GET呼叫也应该失败,但我的GET呼叫工作正常。不管怎样,我在哪里可以添加你提到的代码?有什么特别的过滤器或其他地方吗?你的回答是什么?再次感谢。我要试一试。但是,如果我在HttpSecurity配置中为.requestMatchers(新的RequestHeaderRequestMatcher(“TEST-Header”,“TEST-VALUE”))添加permitAll(),就像为GET添加permitAll()一样,这仍然是因为它对GET有效,而不是对Header有效。它给了我同样的错误。更新了问题以供参考。这是很好的观点。。。。根据这一点,它应该允许。。。你从哪里得到例外?你能添加整个stacktrace吗?@dur我已经更新了问题的详细信息,我在哪里得到了异常。stacktraceElement数组的大小为0,因此堆栈跟踪不可用。刚刚得到我在问题中提到的异常消息。您的
GET
方法是否也用PreAuthorize
注释?对于get
methods.No,您应该会得到相同的异常。GET方法不使用预授权进行注释。这就是它使用GET
方法的原因。如果对某些URL禁用Spring安全性,则无法对该URL使用方法安全性。您必须允许这些URL,而不是忽略URL。
Authentication authentication = new PreAuthenticatedAuthenticationToken("system", null);
authentication.setAuthenticated(true);
context.setAuthentication(authentication);