最近在学习项目的过程中,在登录界面碰到了shiro,在了解到了它主要是用来登录授权的之后,特地写一篇文章来记录一下心得。
shiro是什么?
Apache Shiro是Java的一个安全框架,旨在简化身份验证和授权。Shiro在JavaSE和JavaEE项目中都可以使用。它主要用来处理身份认证,授权,企业会话管理和加密等。
shiro使用流程
开始之前,要进行日常的配置和导包,按着网上的流程来就行了(我的项目是SSM框架)。各种配置好后,首先就是定义shiro拦截器,对url进行拦截,如果没有验证成功的需要验证,然后额外给用户赋予角色和权限。自定义的拦截器需要继承AuthorizingRealm并实现登录验证和赋予角色权限的两个方法:
/**
* 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用,负责在应用程序中决定用户的访问控制的方法
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {
// 因为非正常退出,即没有显式调用 SecurityUtils.getSubject().logout()
// (可能是关闭浏览器,或超时),但此时缓存依旧存在(principals),所以会自己跑到授权方法里。
if (!SecurityUtils.getSubject().isAuthenticated()) {
doClearCache(pc);
SecurityUtils.getSubject().logout();
return null;
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
return info;
}
/**
* 登录信息和用户验证信息验证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authcToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
String username = new String(token.getUsername());// 用户名
String password = new String(token.getPassword());// 密码
UserBean u = userService.findUserBeanByLoginName(username);// 通过登录名 寻找用户
if (u != null) {
// 组合username,两次迭代,对密码进行加密
String pwdEncrypt = CipherHelper.createPwdEncrypt(username,
password, u.getSalt());
AuthenticationInfo auth = null;
if (u.getPasswd().equals(pwdEncrypt)) {
auth = new SimpleAuthenticationInfo(u.getLoginName(), password,
getName());
this.setSession(GlobalConst.SESSION_USER, u);
return auth;
} else {
throw new IncorrectCredentialsException(); /* 错误认证异常 */
}
} else {
throw new UnknownAccountException(); /* 找不到帐号异常 */
}
}
controller:
@RequestMapping(value = "loginApp", produces = "application/json;charset=UTF-8")
@ResponseBody
public Map<String, Object> login(HttpServletRequest request) throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
String errInfo = "";
// shiro管理的session
Subject currentUser = SecurityUtils.getSubject();
String username = request.getParameter("telphone");
String password = request.getParameter("passwd");
String cId = request.getParameter("cId");
// shiro加入身份验证
UsernamePasswordToken token = new UsernamePasswordToken(username, password.toUpperCase());
token.setRememberMe(true);
try {
if (!currentUser.isAuthenticated()) {
currentUser.login(token);
}
// 记录登录日志
} catch (UnknownAccountException uae) {
errInfo = "usererror";// 用户名或密码有误
} catch (IncorrectCredentialsException ice) {
errInfo = "usererror"; // 密码错误
} catch (LockedAccountException lae) {
errInfo = "inactive";// 未激活
} catch (ExcessiveAttemptsException eae) {
errInfo = "attemptserror";// 错误次数过多
} catch (AuthenticationException ae) {
errInfo = "codeerror";// 验证未通过
}
// 验证是否登录成功
if (!currentUser.isAuthenticated()) {
token.clear();
}
if (StringUtils.isEmpty(errInfo)) {
errInfo = "success"; // 验证成功
UserBean bean = userservice.findUserBeanByLoginName(username);
UserBean o = new UserBean();
o.setcId(cId);
o.setId(bean.getId());
userservice.update(o);
currentUser.logout();
}
map.put("result", errInfo);
return map;
}