response.getWriter()

response.getWriter()

参考:

https://blog.csdn.net/zp2605811855/article/details/91852527

在学习Spring Security 图形验证码时, 碰到了一个有趣的问题, 其实还是误解

自定义filter来处理图形验证码

public class ValidateCodeFilter extends OncePerRequestFilter {
    private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();
    @Autowired
    AuthenticationFailureHandler failureHandler;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (isProtectedUrl(request)) {
            try {
                validateCode(new ServletWebRequest(request));
            } catch (ValidateCodeException e) {
                failureHandler.onAuthenticationFailure(request,response,e);
            }
        }
        filterChain.doFilter(request, response);
    }
    
private void validateCode(ServletWebRequest servletWebRequest) throws ServletRequestBindingException {
        //通过session key获取到对应的imageCode
        ImageCode codeInSession = (ImageCode) sessionStrategy
                .getAttribute(servletWebRequest, ValidateController.SESSION_KEY_IMAGE_CODE);
        //从request获取name为imageCode的值
        String codeInRequest = ServletRequestUtils.getStringParameter(servletWebRequest.getRequest(), "imageCode");
        if (StringUtils.isBlank(codeInRequest)){
            throw new ValidateCodeException("验证码不能为空");
        }else if (ObjectUtils.isEmpty(codeInSession)){
            throw new ValidateCodeException("验证码不存在");
        }else if (codeInSession.isExpire()){
            //如果验证码超时失效,删除session中存的值
            sessionStrategy.removeAttribute(servletWebRequest, ValidateController.SESSION_KEY_IMAGE_CODE);
            throw new ValidateCodeException("验证码过期");
        }else if (!StringUtils.equalsIgnoreCase(codeInSession.getCode(),codeInRequest)){
            throw new ValidateCodeException("验证码不正确");
        }
        //如果校验通过, 删除session中的imageCode
        sessionStrategy.removeAttribute(servletWebRequest,ValidateController.SESSION_KEY_IMAGE_CODE);
    }

自定义的failureHandler

public class FailureHandler implements AuthenticationFailureHandler {
    @Autowired
    private ObjectMapper mapper;
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(mapper.writeValueAsString(exception.getMessage()));
    }
}

发现验证码即使错误了也能正常访问, 这就让我百思不得其解

后来发现原来少写了return;

            } catch (ValidateCodeException e) {
                failureHandler.onAuthenticationFailure(request,response,e);
                return;
            }

可是为什么必须加这个return呢? response.getWriter().write()不是直接将字符串写到

页面中了吗?

下面这段时源码中注解

Calling flush() on the PrintWriter commits the response.
Either this method or {@link #getOutputStream} may be called to write the body, not both.

可以大概理解为将内容flush到response 的响应体中, 只有当reponse处理完毕后返回给用户时才会写入到页面,并不是直接输出到页面, 所以这里必须要加return 否则reponse放行了, 就会到下一个filter中

posted @ 2020-05-15 21:58  CyberPelican  阅读(4631)  评论(0编辑  收藏  举报