gpt4 book ai didi

Spring Security 自定义过滤器被多次调用

转载 作者:行者123 更新时间:2023-12-05 08:49:27 27 4
gpt4 key购买 nike

我有一个自定义的 Spring Security 过滤器,它被多次调用,但我无法弄清楚原因。我搜索了它并尝试按照一些帖子的建议添加 FilterRegistrationBean 但我的 Secuirty 过滤器仍然被多次调用并抛出以下错误 -

20:57:49.975 [http-nio-8888-exec-2] DEBUG c.s.m.security.RESTSecurityFilter - Authentication success. Updating SecurityContextHolder to contain: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@fb70fff6: Principal: srib; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@43458: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: BC1D5AB21EE4586F2A76C7901F1F953F; Granted Authorities: ROLE_USER, ROLE_ADMIN
20:57:50.220 [http-nio-8888-exec-2] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: Cannot call sendError() after the response has been committed] with root cause
java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:472)
at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:129)
at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:129)
at org.springframework.security.web.util.OnCommittedResponseWrapper.sendError(OnCommittedResponseWrapper.java:115)
at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:129)
at org.springframework.security.web.util.OnCommittedResponseWrapper.sendError(OnCommittedResponseWrapper.java:115)
at org.springframework.web.servlet.resource.ResourceHttpRequestHandler.handleRequest(ResourceHttpRequestHandler.java:488)
at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:53)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at xxxxxxxxxxxxxxxxxxxxxx.RESTSecurityFilter.successfulAuthentication(RESTSecurityFilter.java:83)

下面是我的配置和过滤器-

RESTSecurityConfig

@Configuration
@EnableWebSecurity
@Order(1)
public class RESTSecurityConfig extends WebSecurityConfigurerAdapter {

@Bean
public RESTSecurityFilter authenticationFilter() throws Exception {
RESTSecurityFilter authenticationFilter = new RESTSecurityFilter("/");
authenticationFilter.setAuthenticationManager(authenticationManagerBean());
return authenticationFilter;
}

@Bean
public RESTAuthenticationProvider authenticationProvider() {
return new RESTAuthenticationProvider();
}

@Bean
public FilterRegistrationBean registration() {
RESTSecurityFilter authenticationFilter = new RESTSecurityFilter("/");
FilterRegistrationBean registration = new FilterRegistrationBean(authenticationFilter);
registration.setEnabled(false);
return registration;
}

@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(authenticationProvider());
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().addFilterAfter(authenticationFilter(),
UsernamePasswordAuthenticationFilter.class);
}
}

RESTSecurityFilter

public class RESTSecurityFilter extends AbstractAuthenticationProcessingFilter {    
private static final Logger log = LoggerFactory.getLogger(RESTSecurityFilter.class);
private static final String ACCESS_KEY_PARAMETER_NAME = "x-access-key";
private static final String SIGNATURE_PARAMETER_NAME = "x-signature";
private static final String NONCE_PARAMETER_NAME = "x-nonce";
private static final String TIMESTAMP_PARAMETER_NAME = "x-timestamp";
private static final String SECRET_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";

protected RESTSecurityFilter(String defaultFilterProcessesUrl) {
super(defaultFilterProcessesUrl);
}

@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
String accessKey = getHeaderValue(request, ACCESS_KEY_PARAMETER_NAME);
String signature = getHeaderValue(request, SIGNATURE_PARAMETER_NAME);
String nonce = getHeaderValue(request, NONCE_PARAMETER_NAME);
String timestamp = getHeaderValue(request, TIMESTAMP_PARAMETER_NAME);

String message = accessKey + ":" + nonce + ":" + timestamp;
String hashSignature = null;
try {

hashSignature = HMacUtility.calculateHmac(message, SECRET_KEY);
log.info("hashSignature : {}", hashSignature);

}
catch (InvalidKeyException | SignatureException | NoSuchAlgorithmException e) {
e.printStackTrace();
}

AbstractAuthenticationToken authRequest = createAuthenticationToken(accessKey,
new RESTCredentials(hashSignature, signature));

// Allow subclasses to set the "details" property
setDetails(request, authRequest);

return this.getAuthenticationManager().authenticate(authRequest);

}

@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
super.successfulAuthentication(request, response, chain, authResult);
chain.doFilter(request, response);
// return; // <--- If uncommented, error goes away but response gets stuck in infinite loop
}

private String getHeaderValue(HttpServletRequest request, String headerParameterName) {
return (request.getHeader(headerParameterName) != null) ? request.getHeader(headerParameterName) : "";
}

private AbstractAuthenticationToken createAuthenticationToken(String apiKeyValue, RESTCredentials restCredentials) {
return new RESTAuthenticationToken(apiKeyValue, restCredentials);
}

protected void setDetails(HttpServletRequest request, AbstractAuthenticationToken authRequest) {
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
}

@Override
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
return true;
}
}

最佳答案

是因为Spring Boot picks up any Filter exposed as a @Bean并将其添加到 ServletContext。通过将其公开为 @Bean 并将其添加到 Spring Security 过滤器链,您已经有效地注册了两次。

很可能,您可以简单地从 authenticationFilter() 方法中删除 @Bean 注释。

关于Spring Security 自定义过滤器被多次调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64090329/

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