目录
普通身份验证与基于表单的拦截器、基于basic的拦截器身份验证的区别?
基于表单的拦截器身份验证和基于 Basic 的拦截器身份验证的区别
普通身份验证与基于表单的拦截器、基于basic的拦截器身份验证的区别?
普通身份验证的一个缺点就是,永远返回到同一个成功页面(比如首页),在实际项目中比如支付时如果没有登录将跳转到登录页面,登录成功后再跳回到支付页面;对于这种功能大家可以在登录时把当前请求保存下来,然后登录成功后再重定向到该请求即可。
Shiro 内置了登录(身份验证)的实现:基于表单的和基于 Basic 的验证,其通过拦截器实现。成功后会自动返回上一个页面,而不是直接跳转到首页或者登陆成功页面
普通身份验证代码如下,需要用代码跳转到登录成功的页面
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String error = null;
String username = req.getParameter("username");
String password = req.getParameter("password");
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
token.setRememberMe(true);
try {
subject.login(token);
} catch (UnknownAccountException e) {
error = "用户名/密码错误";
} catch (IncorrectCredentialsException e) {
error = "用户名/密码错误";
} catch (AuthenticationException e) {
//其他错误,比如锁定,如果想单独处理请单独catch处理
error = "其他错误:" + e.getMessage();
}
if(error != null) {//出错了,返回登录页面
req.setAttribute("error", error);
req.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(req, resp);
} else {//登录成功
req.getRequestDispatcher("/WEB-INF/jsp/loginSuccess.jsp").forward(req, resp);
}
}
基于表单的拦截器身份验证和基于 Basic 的拦截器身份验证的区别
首先这是普通验证的ini文件关于拦截器的配置
[main]
#默认是/login.jsp
authc.loginUrl=/login
roles.unauthorizedUrl=/unauthorized
perms.unauthorizedUrl=/unauthorized
logout.redirectUrl=/login
这是基于表单的拦截器身份验证
[main]
#authc 是 org.apache.shiro.web.filter.authc.FormAuthenticationFilter 类型的实例,其用于实现基于表单的身份验证
authc.loginUrl=/formfilterlogin
authc.usernameParam=username
authc.passwordParam=password
authc.successUrl=/
authc.failureKeyAttribute=shiroLoginFailure
perms.unauthorizedUrl=/unauthorized
roles.unauthorizedUrl=/unauthorized
ini文件中基于表单拦截器的验证与普通拦截器验证的区别体现在后端的判断上
这是普通拦截器的后端判断代码,需要用代码去获取前端用户名与密码属性的值,再去生成token与subject.login对比
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String error = null;
String username = req.getParameter("username");
String password = req.getParameter("password");
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
token.setRememberMe(true);
try {
subject.login(token);
} catch (UnknownAccountException e) {
error = "用户名/密码错误";
} catch (IncorrectCredentialsException e) {
error = "用户名/密码错误";
} catch (AuthenticationException e) {
//其他错误,比如锁定,如果想单独处理请单独catch处理
error = "其他错误:" + e.getMessage();
}
if(error != null) {//出错了,返回登录页面
req.setAttribute("error", error);
req.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(req, resp);
} else {//登录成功
req.getRequestDispatcher("/WEB-INF/jsp/loginSuccess.jsp").forward(req, resp);
}
}
这是基于表单拦截器的后端验证,shiro会自动去验证用户密码的正确性,如果错误则抛出异常名字,写入req的属性中,属性名通过ini配置文件的authc.failureKeyAttribute=shiroLoginFailure指定,failureKeyAttribute 指定登录失败时的 request 属性 key(默认 shiroLoginFailure)
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String errorClassName = (String)req.getAttribute("shiroLoginFailure");
if(UnknownAccountException.class.getName().equals(errorClassName)) {
req.setAttribute("error", "用户名/密码错误");
} else if(IncorrectCredentialsException.class.getName().equals(errorClassName)) {
req.setAttribute("error", "用户名/密码错误");
} else if(errorClassName != null) {
req.setAttribute("error", "未知错误:" + errorClassName);
}
req.getRequestDispatcher("/WEB-INF/jsp/formfilterlogin.jsp").forward(req, resp);
}
对于表单与basic拦截器验证来说,登录成功会自动跳转到上一个页面,不用在代码里面体现