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中