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中