FormAuthenticationFilter有一个方法
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
if (isLoginRequest(request, response)) {
if (isLoginSubmission(request, response)) {
if (log.isTraceEnabled()) {
log.trace("Login submission detected. Attempting to execute login.");
}
return executeLogin(request, response);
} else {
if (log.isTraceEnabled()) {
log.trace("Login page view.");
}
//allow them to see the login page ;)
return true;
}
} else {
if (log.isTraceEnabled()) {
log.trace("Attempting to access a path which requires authentication. Forwarding to the " +
"Authentication url [" + getLoginUrl() + "]");
}
saveRequestAndRedirectToLogin(request, response);
return false;
}
}
写一个子类继承非override这个方法
写一个子类继承于他
protected boolean onAccessDenied(ServletRequest request,
ServletResponse response, Object mappedValue) throws Exception {
// 校验验证码
// 从session获取正确的验证码
HttpSession session = ((HttpServletRequest)request).getSession();
//页面输入的验证码
String randomcode = request.getParameter("randomcode");
//从session中取出验证码
String validateCode = (String) session.getAttribute("validateCode");
if (randomcode!=null && validateCode!=null) {
if (!randomcode.equals(validateCode)) {
// randomCodeError表示验证码错误
request.setAttribute("shiroLoginFailure", "randomCodeError");
//拒绝访问,不再校验账号和密码
return true;
}
}
return super.onAccessDenied(request, response, mappedValue);
}
}
然后用request.setAttribute("shiroLoginFailure", "randomCodeError");设置错误信息,这样能够进行错误控制
第二种错误方式
自定义的FormAuthenticationFilter覆盖父类的onLoginFailure,这个方法能够获取到AuthenticationException从而能够进行错误处理
/**
* 登录失败调用事件
*/
@Override
protected boolean onLoginFailure(AuthenticationToken token,
AuthenticationException e, ServletRequest request, ServletResponse response) {
String className = e.getClass().getName(), message = "";
if (IncorrectCredentialsException.class.getName().equals(className)
|| UnknownAccountException.class.getName().equals(className)){
message = "用户或密码错误, 请重试.";
}
else if (e.getMessage() != null && StringUtils.startsWith(e.getMessage(), "msg:")){
message = StringUtils.replace(e.getMessage(), "msg:", "");
}
else{
message = "系统出现点问题,请稍后再试!";
e.printStackTrace(); // 输出到控制台
}
request.setAttribute(getFailureKeyAttribute(), className);
request.setAttribute(getMessageParam(), message);
return true;
}
然后在登录失败中取出message
* 登录失败,真正登录的POST请求由Filter完成,shiro认证成功后会自动跳转到上一个路径
*/
@RequestMapping(value = "${adminPath}/login")
public String loginFail(HttpServletRequest request, HttpServletResponse response, Model model) {
//判断在FormAuthenticator中有没有错误,即到这一步已经完成了用户的认证
// String exceptionClassName = (String) request.getAttribute("shiroLoginFailure");
// if(exceptionClassName != null){
// if(UnknownAccountException.class.getName().equals(exceptionClassName)){
// throw new CommonException("账号不存在");
// }else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)){
// throw new CommonException("用户名或者密码错误");
// }else{
// throw new CommonException("系统未知错误");
// }
// }
Principal principal = SysUtils.getPrincipal();
// 如果已经登录,则跳转到管理首页
if(principal != null){
return "redirect:" + adminPath;
}
String username = WebUtils.getCleanParam(request, FormAuthenticationFilter.DEFAULT_USERNAME_PARAM);
boolean rememberMe = WebUtils.isTrue(request, FormAuthenticationFilter.DEFAULT_REMEMBER_ME_PARAM);
boolean mobile = WebUtils.isTrue(request, FormAuthenticationFilter.DEFAULT_MOBILE_PARAM);
String exception = (String) request.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);
String message = (String) request.getAttribute(FormAuthenticationFilter.DEFAULT_MESSAGE_PARAM);
if (StringUtils.isBlank(message) || StringUtils.equals(message, "null")) {
message = "用户或密码错误, 请重试!";
根据message返回前台页面即可