package org.superboot.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.xiaoleilu.hutool.crypto.asymmetric.KeyType; import com.xiaoleilu.hutool.crypto.asymmetric.RSA; import com.xiaoleilu.hutool.lang.Base64; import com.xiaoleilu.hutool.util.CharsetUtil; import com.xiaoleilu.hutool.util.StrUtil; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Service; import org.springframework.web.context.request.ServletRequestAttributes; import org.superboot.base.*; import org.superboot.common.pub.Pub_RedisUtils; import org.superboot.common.utils.JWT_Utils; import org.superboot.entity.request.LoginUser; import org.superboot.entity.request.RegisterUser; import org.superboot.entity.request.ReqOtherLogin; import org.superboot.entity.request.Token; import org.superboot.entity.response.ResToken; import org.superboot.remote.UserRemote; import org.superboot.service.PubService; import org.superboot.utils.AESUtil; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; @Service public class PubServiceImpl extends BaseService implements PubService { @Autowired JWT_Utils jwtUtils; @Autowired UserRemote userRemote; @Autowired private Pub_RedisUtils redisUtils; /** * RSA解密 * * @param text 密文 * @return */ private String rsaDecrypt(String text) throws Exception { //使用hutool进行RSA解密,这个的优势是免去使用第三方JAR包的依赖 RSA rsa = new RSA(BaseConstants.DEFAULT_PKCS8_PRIVATE_KEY, BaseConstants.DEFAULT_PUBLIC_KEY); //URL转码 return new String(rsa.decrypt(Base64.decode(text), KeyType.PrivateKey), CharsetUtil.UTF_8); } /** * 获取ASE密钥信息 * * @return */ private String getAesKey() { ServletRequestAttributes attributes = getServletRequestAttributes(); HttpServletRequest request = attributes.getRequest(); String secretKey = request.getHeader(BaseConstants.SECRET_KEY); if (StrUtil.isNotBlank(secretKey)) { //执行RSA解密 try { return rsaDecrypt(secretKey); } catch (Exception e) { throw new BaseException(StatusCode.DECODE_FAIL); } } return null; } /** * 执行数据解密 * * @param value 加密后内容 * @return */ public String aesDecrypt(String value) { String secretKey = getAesKey(); if (null != secretKey) { //解密密文信息 try { String deValue = AESUtil.aesDecrypt(value, secretKey); //临时过渡时期,前端出现的BUG因为部分数字未加密解密后为空串造成接口错误,后期前台改完后此处删除掉 if (StrUtil.isBlank(deValue) && !value.endsWith("=")) { return value; } return deValue; } catch (Exception e) { return value; } } return value; } /** * 设置用户相关信息 * * @param baseToken 用户信息 * @param token token * @return */ private ResToken genResToken(BaseToken baseToken, String token) { ResToken resToken = new ResToken(); //设置TOKEN resToken.setToken(token); //用户账号 resToken.setUserName(baseToken.getUserName()); //设置用户主键 resToken.setUserPk(baseToken.getUserId()); //设置用户公司 resToken.setGroupPk(baseToken.getPkGroup()); //设置关联用户 resToken.setPkEmp(baseToken.getPkEmp()); //设置所属机构 resToken.setPkOrg(baseToken.getPkOrg()); //设置最后登陆日期 resToken.setLoginDate(baseToken.getLoginDate()); //设置最后登陆时间 resToken.setLoginTime(baseToken.getLoginTime()); //账号停用时间 resToken.setEndTime(baseToken.getEndTime()); //用户名称 resToken.setFullName(baseToken.getFullName()); //员工姓名 resToken.setEmpName(baseToken.getEmpName()); //机构名称 resToken.setOrgName(baseToken.getOrgName()); //职务名称 resToken.setDutiesName(baseToken.getDutiesName()); //设置户类型 if (-1 == baseToken.getPkGroup()) { //如果包含系统管理员角色则为系统管理员 if (-1 != baseToken.getUserRole().indexOf(BaseConstants.SYS_ADMIN_NAME)) { resToken.setUserType(-1); } //其他情况为系统级操作用户比如运维 开发人员 else { resToken.setUserType(1); } } else { //如果包含组织管理员角色则为组织管理员 if (-1 != baseToken.getUserRole().indexOf(BaseConstants.GROUP_ADMIN_NAME)) { resToken.setUserType(0); } //如果包含开放注册角色则为公开注册用户 else if (-1 != baseToken.getUserRole().indexOf(BaseConstants.PUB_USER_NAME)) { resToken.setUserType(3); } //其他为组织授权用户 else { resToken.setUserType(2); } } return resToken; } @Override public BaseResponse login(LoginUser loginUser) { if (isAes()) { //执行数据解密 loginUser.setPlatform(aesDecrypt(loginUser.getPlatform())); loginUser.setVersion(aesDecrypt(loginUser.getVersion())); loginUser.setUserCode(aesDecrypt(loginUser.getUserCode())); loginUser.setUserPassword(aesDecrypt(loginUser.getUserPassword())); } //调用用户中心服务获取登陆信息 BaseResponse response = userRemote.login(loginUser); if (BaseStatus.OK.getCode() == response.getStatus()) { //判断数据状态 if (StatusCode.OK.getCode() == response.getCode()) { JSONObject data = (JSONObject) JSON.toJSON(response.getData()); BaseToken bt = JSON.toJavaObject(data, BaseToken.class); //判断白名单,用户是否已经生成过TOKEN了,如果生成过则不再进行登陆操作 String token = getRedisUtils().getTokenAllow(bt.getUserId(), loginUser.getPlatform(), loginUser.getVersion()); if (null == token) { //生成新的TOKEN token = jwtUtils.generateToken(bt); //登陆后将TOKEN信息放入缓存 getRedisUtils().setTokenInfo(token, bt); getRedisUtils().setTokenAllow(bt.getUserId(), loginUser.getPlatform(), loginUser.getVersion(), token); } else { //判断TOKEN是否已经锁定了,如果锁定了则需要重新生成新的TOKEN给客户端 ValueOperations<String, HashMap> operations = getRedisUtils().getRedisTemplate().opsForValue(); boolean exists = getRedisUtils().getRedisTemplate().hasKey(token); if (exists) { HashMap tokenItem = operations.get(token); //如果TOKEN已经锁定,则重新生成TOKEN信息 if (Pub_RedisUtils.TOKEN_STATUS_LOCKED.equals(tokenItem.get(Pub_RedisUtils.TOKEN_STATUS))) { //生成新的TOKEN token = jwtUtils.generateToken(bt); //登陆后将TOKEN信息放入缓存 getRedisUtils().setTokenInfo(token, bt); getRedisUtils().setTokenAllow(bt.getUserId(), loginUser.getPlatform(), loginUser.getVersion(), token); } } } return new BaseResponse(genResToken(bt, token)); } } return response; } @Override public BaseResponse sso(ReqOtherLogin otherLogin) { if (isAes()) { //执行数据解密 otherLogin.setPlatform(aesDecrypt(otherLogin.getPlatform())); otherLogin.setVersion(aesDecrypt(otherLogin.getVersion())); otherLogin.setUserKey(aesDecrypt(otherLogin.getUserKey())); } //调用用户中心服务获取登陆信息 BaseResponse response = userRemote.sso(otherLogin); if (BaseStatus.OK.getCode() == response.getStatus()) { //判断数据状态 if (StatusCode.OK.getCode() == response.getCode()) { JSONObject data = (JSONObject) JSON.toJSON(response.getData()); BaseToken bt = JSON.toJavaObject(data, BaseToken.class); //判断白名单,用户是否已经生成过TOKEN了,如果生成过则不再进行登陆操作 String token = getRedisUtils().getTokenAllow(bt.getUserId(), otherLogin.getPlatform(), otherLogin.getVersion()); if (null == token) { //生成新的TOKEN token = jwtUtils.generateToken(bt); //登陆后将TOKEN信息放入缓存 getRedisUtils().setTokenInfo(token, bt); getRedisUtils().setTokenAllow(bt.getUserId(), otherLogin.getPlatform(), otherLogin.getVersion(), token); } else { //判断TOKEN是否已经锁定了,如果锁定了则需要重新生成新的TOKEN给客户端 ValueOperations<String, HashMap> operations = getRedisUtils().getRedisTemplate().opsForValue(); boolean exists = getRedisUtils().getRedisTemplate().hasKey(token); if (exists) { HashMap tokenItem = operations.get(token); //如果TOKEN已经锁定,则重新生成TOKEN信息 if (Pub_RedisUtils.TOKEN_STATUS_LOCKED.equals(tokenItem.get(Pub_RedisUtils.TOKEN_STATUS))) { //生成新的TOKEN token = jwtUtils.generateToken(bt); //登陆后将TOKEN信息放入缓存 getRedisUtils().setTokenInfo(token, bt); getRedisUtils().setTokenAllow(bt.getUserId(), otherLogin.getPlatform(), otherLogin.getVersion(), token); } } } return new BaseResponse(genResToken(bt, token)); } } return response; } @Override public BaseResponse tokenInfo() { ServletRequestAttributes attributes = getServletRequestAttributes(); HttpServletRequest request = attributes.getRequest(); String token = request.getHeader(BaseConstants.TOKEN_KEY); if (StringUtils.isBlank(token)) { throw new BaseException(StatusCode.TOKEN_INVALID); } BaseToken baseToken = getBaseToken(); return new BaseResponse(genResToken(baseToken, token)); } /** * 数据是否进行加密,部分接口不允许不加密请求 * * @return */ private boolean isAes() { if (StrUtil.isBlank(getAesKey())) { return false; } return true; } @Override public BaseResponse logout(String token) { //获取用户信息 BaseToken bt = getRedisUtils().getTokenInfo(token); //清理TOKEN白名单信息 getRedisUtils().cleanTokenAllow(bt.getUserId(), token); //从Redis中清理TOKEN信息 getRedisUtils().getRedisTemplate().delete(token); return new BaseResponse(StatusCode.OPERATION_SUCCESS); } @Override public BaseResponse register(RegisterUser registerUser) { if (!isAes()) { //执行数据解密 registerUser.setPlatform(aesDecrypt(registerUser.getPlatform())); registerUser.setVersion(aesDecrypt(registerUser.getVersion())); registerUser.setUserCode(aesDecrypt(registerUser.getUserCode())); registerUser.setUserPassword(aesDecrypt(registerUser.getUserPassword())); registerUser.setUserEmail(aesDecrypt(registerUser.getUserEmail())); registerUser.setUserPhone(aesDecrypt(registerUser.getUserPhone())); registerUser.setUserName(aesDecrypt(registerUser.getUserName())); registerUser.setEndTime(aesDecrypt(registerUser.getEndTime())); } BaseResponse response = userRemote.addUser(registerUser); if (BaseStatus.OK.getCode() == response.getStatus()) { //判断数据状态 if (StatusCode.ADD_SUCCESS.getCode() == response.getCode()) { JSONObject data = (JSONObject) JSON.toJSON(response.getData()); BaseToken bt = JSON.toJavaObject(data, BaseToken.class); //判断白名单,用户是否已经生成过TOKEN了,如果生成过则不再进行登陆操作 String token = getRedisUtils().getTokenAllow(bt.getUserId(), registerUser.getPlatform(), registerUser.getVersion()); if (null == token) { //生成新的TOKEN token = jwtUtils.generateToken(bt); //登陆后将TOKEN信息放入缓存 getRedisUtils().setTokenInfo(token, bt); getRedisUtils().setTokenAllow(bt.getUserId(), registerUser.getPlatform(), registerUser.getVersion(), token); } return new BaseResponse(StatusCode.ADD_SUCCESS, genResToken(bt, token)); } } return response; } @Override public BaseResponse refresh(String token) { if (null == token) { throw new BaseException(StatusCode.TOKEN_NOT_FIND); } //刷新生成新的TOKEN String tokenStr = jwtUtils.refreshToken(token); if (null == tokenStr) { throw new BaseException(StatusCode.TOKEN_INVALID); } //根据老的TOKEN获取用户信息 BaseToken baseToken = getRedisUtils().getTokenInfo(token); //判断白名单,用户是否已经生成过TOKEN了,如果生成过则不再进行登陆操作 HashMap<String, String> tokenItem = getRedisUtils().getTokenAllowItem(baseToken.getUserId(), token); if (null == token) { throw new BaseException(StatusCode.TOKEN_INVALID); } else { String version = tokenItem.get(BaseConstants.TOKEN_VERSION); String platform = tokenItem.get(BaseConstants.TOKEN_PLATFORM); //清理TOKEN getRedisUtils().cleanTokenAllow(baseToken.getUserId(), token); //从Redis中清理TOKEN信息 getRedisUtils().getRedisTemplate().delete(token); //更新缓存信息 getRedisUtils().setTokenInfo(tokenStr, baseToken); //更新新的TOKEN到白名单 getRedisUtils().setTokenAllow(baseToken.getUserId(), platform, version, tokenStr); } return new BaseResponse(genResToken(baseToken, tokenStr)); } @Override public BaseResponse locked(Token oldToken) { getRedisUtils().tokenLocked(oldToken.getToken(), true); return new BaseResponse(StatusCode.LOCKED_SUCCESS); } @Override public BaseResponse unLocked(Token oldToken) { getRedisUtils().tokenLocked(oldToken.getToken(), false); return new BaseResponse(StatusCode.UNLOCKED_SUCCESS); } @Override public BaseResponse checkUserIsManager(String token) { BaseToken baseToken = getRedisUtils().getTokenInfo(token); if (null != baseToken) { //判断用户的角色是否为空 if (!StringUtils.isBlank(baseToken.getUserRole())) { //获取系统有操作权限的角色 String[] roles = BaseConstants.ADMIN_ROLE_TYPE.split(","); for (String role : roles) { if (-1 != role.indexOf(baseToken.getUserRole())) { return new BaseResponse(StatusCode.AUTHORIZATION_OPERATION); } } } } return new BaseResponse(StatusCode.UNAUTHORIZED_OPERATION); } }