- 在使用shiro的时候用户登录后关闭网页(未注销)的情况下,如果用户这个时候再输入用户名和密码进行登陆的时候shiro就会报一个“错误”。
- 原因产生
- 请求访问的时候访问流程是请求-》过滤器-》Controller,只有在过滤器返回true的时候才会进行Controller的访问。在此案例中,由于已经登录过了在进行过滤器的时候由于已经登录了返回ture,直接访问了Controller,而此时的Controller是登录的路径,那么就会访问到登录的Contoller,跳转到了如下Controller,由于已经登录但是未发现异常直接返回了到了首页。
@Controller
@RequestMapping("/user")
public class UsersController {
/**
* 注入登录的页面
*/
@Autowired
private UserLoginService usersLoginService;
/**
* @description: 登录失败跳转到登录页面并携带信息
* @param model
* @param request
* @return: java.lang.String
* @author: shinelon
* @time: 2019/8/7:10:31
*/
@RequestMapping(value = "/login")
public String login(Model model, HttpServletRequest request) {
String ex = (String) request.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);
//判断方法异常
if (UnknownAccountException.class.getName().equals(ex)) {
model.addAttribute("errorInfo", "用户名错误!!");
} else if (IncorrectCredentialsException.class.getName().equals(ex)) {
model.addAttribute("errorInfo", "未知凭证!!");
} else {
model.addAttribute("errorInfo", "未知异常");
}
return "index";
}
}
具体原因是再执行登陆的时候会调用org.apache.shiro.web.filter.AccessControlFilter类里面的onPreHandle方法。
在使用Shiro框架的时候所有的请求经过过滤器都会来到此onPreHandle方法
- isAccessAllowed:判断是否登录
-
- 在登录的情况下会走此方法,此方法返回true直接访问控制器
-
- onAccessDenied:是否是拒绝登录
-
- 没有登录的情况下会走此方法
-
public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
return this.isAccessAllowed(request, response, mappedValue) || this.onAccessDenied(request, response, mappedValue);
}
如果isAccessAllowed方法返回True,则不会再调用onAccessDenied方法,如果isAccessAllowed方法返回Flase,则会继续调用onAccessDenied方法。而onAccessDenied方法里面则是具体执行登陆的地方。由于我们已经登陆,所以此方法就会返回True(filter放行),所以上面的onPreHandle方法里面的onAccessDenied方法就不会被执行。
- 解决办法
-
- 让它在走一次登录流程即可
- 重写过滤器的isAccessAllowed方法,判断请求是否为登录请求和登录提交请求,如果是就返回false,如果不是则继续按照原先的代码流程进行走
-
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
if(isLoginRequest(request,response)&&isLoginSubmission(request,response)){
return false;
}
return super.isAccessAllowed(request, response, mappedValue);
}