Sanji
1
我自定义了一个过滤器,用于对验证码进行校验,大概如下:
public class CaptchaFilter extends OncePerRequestFilter {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {
....
}
}
在过滤方法中,我过滤了特定的POST和PUT方法,也写了filterChain.doFilter(request, response);
,但是到了controller,同一个url对应的@PostMapping和@PutMapping却无法区分了,总是报405错误。
求助各位,帮忙看看可能是哪里有问题?
你是想通过拦截器统一校验验证码吗?405是请求方式不支持,你的信息太少了,不怎么好确定问题。
Sanji
3
我是想实现一个统一的验证码校验,但是,现在情况看起来就是:一个请求经过了上面的过滤器后,到了Controller就不能使用RESTful风格的请求了,无法区分请求方法了,比如同一个url同时存在@PostMapping和@PutMapping,就会报405错误。
过滤器的实现如下:
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// 确定请求路径是否需要验证验证码
boolean condition = false;
for (String path : captchaFilterPathList) {
condition = MATCHER.match(path, request.getServletPath());
if (condition) break;
}
// 只拦截POST和PUT方法
if (condition && (HttpMethod.POST.name().equals(request.getMethod())) ||
HttpMethod.PUT.name().equals(request.getMethod())) {
// 做验证
try {
doCaptchaValidation(request);
// 验证无误后进入下一个过滤器,否则应该在此终止
filterChain.doFilter(request, response);
} catch (CaptchaException exception) {
request.getRequestDispatcher(captchaFailureHandlePath + "?message=" + URLEncoder.encode(exception.getMessage(), "UTF-8")).forward(request, response);
}
} else {
filterChain.doFilter(request, response);
}
}
private void doCaptchaValidation(HttpServletRequest request) throws CaptchaException {
logger.debug("正在做验证码验证。。。");
String captcha = request.getParameter(requestParameterKey);
request.removeAttribute(requestParameterKey);
Object credentials = request.getSession().getAttribute(sessionAttributeKey);
if (captcha == null) {
throw new CaptchaException("验证码不能为空");
} else if (credentials == null) {
throw new CaptchaException("会话已经过期,请刷新验证码");
} else {
CharImageCaptcha imageCaptcha = (CharImageCaptcha) credentials;
if (imageCaptcha.isExpired()) {
throw new CaptchaException("验证码已经过期,请刷新验证码");
} else if (captcha.toUpperCase().equals(imageCaptcha.getCode())) {
// 验证成功,删除session中的验证码
request.getSession().removeAttribute(sessionAttributeKey);
} else {
// 验证码不匹配
throw new CaptchaException("验证码输入错误");
}
}
}
还是看不出来啥问题,你可以试试看用拦截器实现。拦截器,拦截固定的路径,不用每次都去执行遍历判断是否是要验证的url。配合自定义注解,可以更灵活的控制验证行为。通过异常处理器来提示客户端验证码错误。
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
Captcha captcha = handlerMethod.getMethodAnnotation(Captcha.class);
if (captcha == null) {
return Boolean.TRUE;
}
String code = request.getParameter(captcha.value());
if (!StringUtils.isEmpty(code)) { // 验证码参数非空
HttpSession session = request.getSession(Boolean.FALSE);
if (session != null) {
Object attr = session.getAttribute(SessionKeys.CAPTCHA);
if (attr != null && code.equalsIgnoreCase((String) attr)) {
if (captcha.invalidateSession()) {
session.invalidate(); // 验证ok,失效会话
}
return Boolean.TRUE;
}
}
}
throw new ServiceException(Message.fail(HttpStatus.BAD_REQUEST, "验证码错误"));
}
也许你可以试试看
Sanji
6
不好意思,我知道错误在哪了,不是RESTful出了问题,是在转发的时候出了问题,感谢 KevinBlandy的支持,非常抱歉耽误您的时间。
1 个赞