Spring Security 过滤器异常:getWriter() has already been called for this response

 java.lang.IllegalStateException: getWriter() has already been called for this response

异常:

09:26:47.102 ERROR c.b.b.config.DefaultExceptionHandler  path:/user-base/user/verifyIdentity, queryParam:null, errorMessage:getWriter() has already been called for this response
java.lang.IllegalStateException: getWriter() has already been called for this response
	at org.apache.catalina.connector.Response.getOutputStream(Response.java:550)
	at org.apache.catalina.connector.ResponseFacade.getOutputStream(ResponseFacade.java:210)
	at javax.servlet.ServletResponseWrapper.getOutputStream(ServletResponseWrapper.java:105)
	at javax.servlet.ServletResponseWrapper.getOutputStream(ServletResponseWrapper.java:105)
	at org.springframework.security.web.util.OnCommittedResponseWrapper.getOutputStream(OnCommittedResponseWrapper.java:145)
	at org.springframework.http.server.ServletServerHttpResponse.getBody(ServletServerHttpResponse.java:84)
	at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:313)
	at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:104)
	at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:277)
	at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:181)
	at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:82)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:123)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	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:626)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at com.biaopu.core.interceptor.TokenVerifyFilter.doFilterInternal(TokenVerifyFilter.java:86)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)
	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)

报错位置:chain.doFilter(request, response);

package com.biaopu.core.interceptor;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.biaopu.core.handler.TokenHandleUtil;
import com.biaopu.core.mapper.SysUserMapper;
import com.biaopu.core.pojo.entity.SysUser;
import com.biaopu.core.utils.UserUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * 校验Token是否合法的Filter
 */
@Slf4j
public class TokenVerifyFilter  extends BasicAuthenticationFilter {
    @Autowired
    private TokenStore tokenStore;
    @Autowired
    private SysUserMapper sysUserMapper;
    private static TokenVerifyFilter tokenVerifyFilter;

    public TokenVerifyFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }
    @PostConstruct
    private void init () {
        tokenVerifyFilter = this;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        String header = request.getHeader("Authorization");
        PrintWriter out = response.getWriter();//报错原因  与controller中返回值冲突
        Map resultMap = new HashMap();
        if (header == null || !header.startsWith("Bearer")) {
            //如果携带错误的token,则给用户提示请登录!
            chain.doFilter(request, response);
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            resultMap.put("code", HttpServletResponse.SC_FORBIDDEN);
            resultMap.put("msg", "携带错误的token!");

        } else {
            //如果携带了正确格式的token要先得到token
//            String token = header.replace("Bearer", "");
            String str [] =header.split(" ");
            String token = str[1];
            log.info("send {} to {}",request.getMethod(),request.getRequestURL().toString());

            if(null == token){
                log.error("token is null ...");
                resultMap.put("code", HttpServletResponse.SC_FORBIDDEN);
                resultMap.put("msg", "携带的token is null ...");
            }else{
                //校验是否存在redis中
                TokenHandleUtil tokenHandleUtil = new TokenHandleUtil();
                Long userId = UserUtils.getUserId(request);
                Boolean flag  = tokenHandleUtil.verifyToken(token,userId);
                if (flag) {
                    //校验redis中token是否有效
                    log.info("access token is ok!!!");
                    UsernamePasswordAuthenticationToken authResult =
                            new UsernamePasswordAuthenticationToken(userId, null, null);
                    SecurityContextHolder.getContext().setAuthentication(authResult);
                    
                    chain.doFilter(request, response);//这里报错
                }
            }
        }
        out.write(resultMap.toString());
        out.flush();
        out.close();
    }


}

原因:

controller中设置了返回方法,过滤器中又调用了PrintWriter ,冲突报错

PrintWriter out = response.getWriter();

 解决方式:

去掉PrintWriter,或者将PrintWriter移动到if内

if (header == null || !header.startsWith("Bearer")) {

    //如果携带错误的token,则给用户提示请登录!
    response.setContentType("application/json;charset=utf-8");
    response.setStatus(HttpServletResponse.SC_FORBIDDEN);
    resultMap.put("code", HttpServletResponse.SC_FORBIDDEN);
    resultMap.put("msg", "携带错误的token!");
    PrintWriter out = response.getWriter();
    out.write(resultMap.toString());
    out.flush();
    out.close();

} else {
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当调用response的getWriter()方法时,表示已经在该响应对象上调用了一次getWriter()方法。再次调用该方法会导致报错"getWriter() has already been called for this response"。这种情况通常发生在过滤器中。根据提供的引用内容,可以看出在filter中的第一次调用了getWriter()方法,然后继续执行controller层的方法后,又一次调用了getWriter()方法,导致报错。 针对这个问题,网上的解决办法通常是在调用完getWriter()方法后,手动调用writer.flush()方法来结束调用。但是根据提供的引用内容来看,尝试了这个解决办法之后并没有有效果。 我们可以看到,在提供的代码中,在调用getWriter()方法之前没有判断是否已经调用过getWriter()方法。为了解决这个问题,可以在调用getWriter()方法之前添加判断,如果已经调用过getWriter()方法,则不再调用。可以通过设置一个标志位来记录是否已经调用过getWriter()方法。例如,在filter中定义一个布尔类型的变量hasGetWriter,初始值为false,第一次调用getWriter()方法时将其设置为true,后续再次调用getWriter()方法时先判断hasGetWriter的值,如果为true则不再调用getWriter()方法,避免重复调用导致报错。 总结来说,当过滤器中的response对象重复调用getWriter()方法时,会报错"getWriter() has already been called for this response"。可以通过添加判断来避免重复调用getWriter()方法,解决这个问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [解决filter中的getWriter() has already been called for this response异常](https://blog.csdn.net/haoqingt1/article/details/112350623)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值