SecurityFilter被多次调用-提交响应后无法调用sendError

问题描述

从AuthenticationProvider成功进行身份验证后,Spring安全性出现错误。从堆栈跟踪中看起来像多次调用Spring Security Filter。

java.lang.IllegalStateException: Cannot call sendError() after the response has been committed

我已经在这里发布了关于我的问题的问题-Spring Security - Unable to Autowire UserDetailsService in DaoAuthenticationProvider在这里,我试图使用DaoAuthenticationProvider,但是没有运气。

因此,尝试立即使用身份验证提供程序并获得错误。 SpringSecurity Filter被多次调用的原因可能是什么。请帮忙!

这是我当前的代码-

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() {
        RESTAuthenticationProvider provider = new RESTAuthenticationProvider();
        return provider;
    }

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {    
 http.authorizeRequests().anyRequest().authenticated().and().addFilterBefore(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;
    }
}

RestAuthenticationProvider

public class RESTAuthenticationProvider implements AuthenticationProvider {
    private static final Logger log = LoggerFactory.getLogger(RESTAuthenticationProvider.class);

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException{
        String userName = authentication.getName();
        RESTCredentials credentials = (RESTCredentials) authentication.getCredentials();
        String cred1 = credentials.getRequestSalt();
        String cred2 = credentials.getSecureHash();
        Authentication auth = null;

        List<String> rolesList = new ArrayList<>();
        rolesList.add("ROLE_USER");
        rolesList.add("ROLE_ADMIN");

        if (userName.equals("abc") && cred1.equalsIgnoreCase(cred2)) {
            Collection<GrantedAuthority> grantedAuths = new ArrayList<>();
            for (String role : rolesList) {
                grantedAuths.add(new SimpleGrantedAuthority(role.trim()));
            }
            auth = new UsernamePasswordAuthenticationToken(userName,cred1,grantedAuths);
            return auth;
        }
        else {
            throw new BadCredentialsException("Invalid credentials!");
        }
    }

    @Override
    public boolean supports(Class<? extends Object> authentication) {
        return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
    }    
}

错误的堆栈跟踪-

10:34:46.336 [http-nio-8888-exec-1] DEBUG c.s.m.security.RESTSecurityFilter - Authentication success. Updating SecurityContextHolder to contain: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@fb74cbae: Principal: srib; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_USER,ROLE_ADMIN
10:34:46.338 [http-nio-8888-exec-1] 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 xxxxxxxxxxxxxxxxxxxxx.security.RESTSecurityFilter.successfulAuthentication(RESTSecurityFilter.java:86)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:240)

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)