package com.gkhy.assess.framework.shiro.service;
|
|
import com.gkhy.assess.common.constant.CacheConstant;
|
import com.gkhy.assess.common.enums.ApproveStatusEnum;
|
import com.gkhy.assess.common.enums.UserIdentityEnum;
|
import com.gkhy.assess.common.enums.UserStatusEnum;
|
import com.gkhy.assess.common.exception.ApiException;
|
import com.gkhy.assess.common.utils.JwtTokenUtil;
|
import com.gkhy.assess.common.utils.RedisUtils;
|
import com.gkhy.assess.system.domain.SysUser;
|
import com.gkhy.assess.system.service.SysUserService;
|
import com.gkhy.assess.system.utils.ShiroUtils;
|
import org.apache.commons.lang3.StringUtils;
|
import org.apache.shiro.authc.AuthenticationException;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Component;
|
|
import java.time.LocalDateTime;
|
|
@Component
|
public class SysLoginService {
|
@Autowired
|
private SysUserService sysUserService;
|
@Autowired
|
private SysPasswordService passwordService;
|
@Autowired
|
private RedisUtils redisUtils;
|
|
public SysUser login(String username, String password) {
|
SysUser sysUser=sysUserService.getUserByUsernamePhone(username);
|
validUser(sysUser);
|
passwordService.validate(sysUser,password);
|
recordLoginInfo(sysUser.getId());
|
return sysUser;
|
}
|
|
public void validUser(SysUser sysUser){
|
if(sysUser==null) {
|
throw new AuthenticationException("用户不存在");
|
}
|
if(UserStatusEnum.DELETED.getCode().equals(sysUser.getDelFlag())){
|
throw new AuthenticationException("用户已被删除");
|
}
|
if(UserStatusEnum.DISABLE.getCode().equals(sysUser.getStatus())){
|
throw new AuthenticationException("用户已被停用");
|
}
|
if(UserIdentityEnum.AGENCY.getCode().equals(sysUser.getIdentity())){
|
if(!ApproveStatusEnum.APPROVED.getCode().equals(sysUser.getState())){
|
throw new AuthenticationException("机构账户审批还未通过");
|
}
|
}
|
}
|
|
public SysUser validJwtToken(String jwtToken){
|
String username= JwtTokenUtil.getUsername(jwtToken);
|
if(StringUtils.isEmpty(username)){
|
throw new AuthenticationException("token非法无效!");
|
}
|
SysUser sysUser=sysUserService.getUserByUsernamePhone(username);
|
validUser(sysUser);
|
if(!jwtTokenRefresh(jwtToken,username,sysUser.getPassword())){
|
throw new AuthenticationException("Token失效,请重新登录!");
|
}
|
// setRolePermission(sysUser);
|
return sysUser;
|
}
|
|
/**
|
* JWTToken刷新生命周期 (实现: 用户在线操作不掉线功能)
|
* 1、登录成功后将用户的JWT生成的Token作为k、v存储到cache缓存里面(这时候k、v值一样),缓存有效期设置为Jwt有效时间的2倍
|
* 2、当该用户再次请求时,通过JWTFilter层层校验之后会进入到doGetAuthenticationInfo进行身份验证
|
* 3、当该用户这次请求jwt生成的token值已经超时,但该token对应cache中的k还是存在,则表示该用户一直在操作只是JWT的token失效了,程序会给token对应的k映射的v值重新生成JWTToken并覆盖v值,该缓存生命周期重新计算
|
* 4、当该用户这次请求jwt在生成的token值已经超时,并在cache中不存在对应的k,则表示该用户账户空闲超时,返回用户信息已失效,请重新登录。
|
* 注意: 前端请求Header中设置Authorization保持不变,校验有效性以缓存中的token为准。
|
* 用户过期时间 = Jwt有效时间 * 2。
|
*
|
* @param username
|
* @param passWord
|
* @return
|
*/
|
public boolean jwtTokenRefresh(String jwtToken,String username,String passWord){
|
String tokenKey=redisUtils.generateKey(CacheConstant.SYS_USER_TOKEN+":"+JwtTokenUtil.md5Encode(jwtToken));
|
String userKey=redisUtils.generateKey(CacheConstant.SYS_USER_TOKEN+":"+username);
|
String cacheToken= (String) redisUtils.get(tokenKey);
|
if(StringUtils.isNotEmpty(cacheToken)){
|
// 校验token有效性
|
if(!JwtTokenUtil.verify(cacheToken,username,passWord)){
|
String newToken=JwtTokenUtil.sign(username,passWord);
|
// 设置超时时间
|
redisUtils.set(tokenKey,newToken);
|
redisUtils.expire(tokenKey,JwtTokenUtil.EXPIRATION*2/1000);
|
redisUtils.expire(userKey,(JwtTokenUtil.EXPIRATION*2/1000)+2);
|
}
|
return true;
|
}
|
return false;
|
}
|
|
|
public void recordLoginInfo(Long userId){
|
SysUser user=new SysUser();
|
user.setId(userId);
|
user.setLoginIp(ShiroUtils.getIp());
|
user.setLoginDate(LocalDateTime.now());
|
sysUserService.updateById(user);
|
|
}
|
}
|