前言
Shiro是我们经常用的一个用户权限的工具。在我们工作中,我们有可能刚刚编辑好了一个系统,但是新的需求又出来了。假定有这么一种情况,我们系统的原来的用户表需要用,但是呢,我们不想改变原来的用户表结构,这就会催使我们建立一个新的用户表,这个时候我们怎么办呢?本节内容就是说的这件事。
这么实现的前提条件是,我们需要升级系统,但是,我们不想改变原来的系统的结构,这就催使我们增加新的额数据库表。很有可能增加的是我们的用户表,这个时候,我们如何有效的管理我们的用户的登陆呢,所以今天讲述的是Shiro的多用户的登陆操作。
我们实现的主要思路是,我们要改变重写UsernamePasswordToken,加上所属的功能,来判断是原来的用户登陆还是,我们新增加的用户登陆。之后我们要改变用户的认证逻辑,具体的实现方法如下。
正文
重写UsernamePasswordToken
重写这个类,实质上是我们的Java代码继承这个类,来实现我们的想要的功能。
/** * 自己定义token * * @date : 2018/01/02 */ @Getter public class LocalUsernamePasswordToken extends UsernamePasswordToken { /** * 远端的IP */ private String remoteIp; private String function; private UserCategoryEnum belongUser; public LocalUsernamePasswordToken(String username, String password, String remoteIp, UserCategoryEnum belongUser) { super(username, password); this.remoteIp = remoteIp; this.belongUser = belongUser; } public LocalUsernamePasswordToken(String username, String password, String remoteIp, String function, UserCategoryEnum belongUser) { super(username, password); this.remoteIp = remoteIp; this.function = function; this.belongUser = belongUser; } }
重构登陆的实现代码
@Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { /** * 判断是否为自己重新写的 */ if (token instanceof LocalUsernamePasswordToken) { LocalUsernamePasswordToken usernamePasswordToken = (LocalUsernamePasswordToken) token; if (UserCategoryEnum.SYSTEM.getUserCategoryMessage().equals(usernamePasswordToken.getBelongUser().getUserCategoryMessage())) { /** * 系统用户 */ String username = usernamePasswordToken.getUsername(); UserService userService = SpringUtil.getBean(UserService.class); User user = userService.getUser(username); if (user == null) { throw new UnknownAccountException("用户名不存在"); } if (!user.getPassword() .equals(userService.passwordEncoder(new String(usernamePasswordToken.getPassword()), user.getSalt()))) { throw new IncorrectCredentialsException("密码错误"); } if (user.getStatus() != User.Status.VALID) { throw new IncorrectCredentialsException("无效状态,请联系管理员"); } SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, new String(usernamePasswordToken.getPassword()), getName()); UserUtil.setUserSession(user); return authenticationInfo; } else { /** * 企业用户平台用户 */ String username = usernamePasswordToken.getUsername(); if (null == username || "".equals(username)) { log.error("您填写的用户名为空!"); throw new UnknownAccountException("您填写的用户名为空!"); } if (!username.matches(PHONE_REGEX)) { log.error("您填写的手机号格式不对!"); throw new UnknownAccountException("您填写的手机号格式不对!"); } List<FinanceUserEntity> financeUserEntityByPhoneNumber = financeUserService.getFinanceUserEntityByPhoneNumber(username); FinanceUserEntity financeUserEntity = null; if (null != financeUserEntityByPhoneNumber && financeUserEntityByPhoneNumber.size() > 0) { financeUserEntity = financeUserEntityByPhoneNumber.get(0); String clientSalt = financeUserEntity.getClientSalt(); String password = new String(usernamePasswordToken.getPassword()); String passwordMd5 = LocalGeneratePasswordUtil.generatePasswordByPassSalt(password, clientSalt); if (!financeUserEntity.getClientPassword().equals(passwordMd5)) { throw new IncorrectCredentialsException("密码错误"); } Date nowTime = new Date(); financeUserEntity.setLastLoginDate(nowTime); financeUserEntity.setLastLoginIp(usernamePasswordToken.getRemoteIp()); Integer loginCount = financeUserEntity.getLoginCount(); if (null == loginCount) { /** * 第一次登录 */ loginCount = 1; } else { loginCount++; } financeUserEntity.setLoginCount(loginCount); financeUserEntity.setGmtModified(nowTime); financeUserService.updateFinanceUserByPhoneNumber(financeUserEntity); } else { throw new UnknownAccountException("用户名不存在"); } SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(financeUserEntity, new String(usernamePasswordToken.getPassword()), getName()); UserUtil.setFinanceUserSession(financeUserEntity); return authenticationInfo; } } else { throw new UnknownAccountException("联系管理员 不是LocalUsernamePasswordToken的对象"); } }
我们看到,我们用了一个判断来实现不同的对象,这样我们就实现了Shiro多种用户登陆。