UserProvider.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. package jnpf.util;
  2. import cn.dev33.satoken.same.SaSameUtil;
  3. import cn.dev33.satoken.session.SaSession;
  4. import cn.dev33.satoken.session.SaTerminalInfo;
  5. import cn.dev33.satoken.stp.StpUtil;
  6. import cn.dev33.satoken.stp.parameter.SaLoginParameter;
  7. import cn.hutool.core.text.StrPool;
  8. import jnpf.base.UserInfo;
  9. import jnpf.consts.DeviceType;
  10. import lombok.extern.slf4j.Slf4j;
  11. import org.springframework.stereotype.Component;
  12. import org.springframework.util.ObjectUtils;
  13. import java.util.List;
  14. import java.util.stream.Collectors;
  15. import static jnpf.consts.AuthConsts.TOKEN_PREFIX_SP;
  16. /**
  17. * @author JNPF开发平台组
  18. * @version V3.1.0
  19. * @copyright 引迈信息技术有限公司
  20. * @date 2021/3/16 10:57
  21. */
  22. @Slf4j
  23. @Component
  24. public class UserProvider {
  25. private static RedisUtil redisUtil;
  26. private static CacheKeyUtil cacheKeyUtil;
  27. public static final String USER_INFO_KEY = "userInfo";
  28. private static final ThreadLocal<UserInfo> USER_CACHE = new ThreadLocal<>();
  29. public UserProvider(RedisUtil redisUtil, CacheKeyUtil cacheKeyUtil) {
  30. UserProvider.redisUtil = redisUtil;
  31. UserProvider.cacheKeyUtil = cacheKeyUtil;
  32. }
  33. // =================== 登录相关操作 ===================
  34. /**
  35. * 登录系统 适用于Request环境
  36. *
  37. * @param userInfo 登录用户信息
  38. */
  39. public static void login(UserInfo userInfo) {
  40. setLocalLoginUser(userInfo);
  41. StpUtil.login(splicingLoginId(userInfo.getUserId()));
  42. userInfo.setToken(StpUtil.getTokenValueNotCut());
  43. userInfo.setSecurityKey(DesUtil.aesOrDecode(TicketUtil.createTicket(userInfo.getToken(), 10*24*60*60000L), true, true));
  44. setLoginUser(userInfo);
  45. }
  46. /**
  47. * 登录系统 适用于Request环境
  48. *
  49. * @param userInfo 用户信息
  50. * @param loginModel 登录参数
  51. */
  52. public static void login(UserInfo userInfo, SaLoginParameter loginModel) {
  53. setLocalLoginUser(userInfo);
  54. StpUtil.login(splicingLoginId(userInfo.getUserId()), loginModel);
  55. userInfo.setToken(StpUtil.getTokenValueNotCut());
  56. userInfo.setSecurityKey(DesUtil.aesOrDecode(TicketUtil.createTicket(userInfo.getToken(), 10*24*60*60000L), true, true));
  57. setLoginUser(userInfo);
  58. }
  59. /**
  60. * 适用于非Request环境
  61. * @param userInfo
  62. * @param loginModel
  63. */
  64. public static void loginNoRequest(UserInfo userInfo, SaLoginParameter loginModel) {
  65. setLocalLoginUser(userInfo);
  66. String token = StpUtil.createLoginSession(splicingLoginId(userInfo.getUserId()), loginModel);
  67. userInfo.setToken(TOKEN_PREFIX_SP + token);
  68. setLoginUser(userInfo);
  69. }
  70. // =================== 登录用户ID相关操作 ===================
  71. /**
  72. * 获取指定TOKEN用户ID
  73. *
  74. * @param token
  75. * @return
  76. */
  77. public static String getLoginUserId(String token) {
  78. String loginId = (String) StpUtil.getLoginIdByToken(token);
  79. return parseLoginId(loginId);
  80. }
  81. /**
  82. * 获取当前用户ID, 包含临时切换用户ID
  83. *
  84. * @return
  85. */
  86. public static String getLoginUserId() {
  87. String loginId = getUser().getUserId();
  88. return parseLoginId(loginId);
  89. }
  90. // =================== 用户ID拼接相关操作 ===================
  91. /**
  92. * 拼接租户下的用户ID
  93. *
  94. * @param userId
  95. * @return
  96. */
  97. public static String splicingLoginId(String userId) {
  98. return splicingLoginId(userId, null);
  99. }
  100. /**
  101. * 拼接租户下的用户ID
  102. * @param userId
  103. * @param tenantId
  104. * @return
  105. */
  106. private static String splicingLoginId(String userId, String tenantId) {
  107. if(StringUtil.isEmpty(tenantId)){
  108. tenantId = TenantHolder.getDatasourceId();
  109. }
  110. if (!StringUtil.isEmpty(tenantId)) {
  111. return tenantId + StrPool.COLON + userId;
  112. }
  113. return userId;
  114. }
  115. /**
  116. * 解析租户下的登录ID
  117. * @param loginId
  118. * @return
  119. */
  120. private static String parseLoginId(String loginId) {
  121. if (loginId != null && loginId.contains(StrPool.COLON)) {
  122. loginId = loginId.substring(loginId.indexOf(StrPool.COLON) + 1);
  123. }
  124. return loginId;
  125. }
  126. /**
  127. * Token是否有效
  128. *
  129. * @param token
  130. * @return
  131. */
  132. public static Boolean isValidToken(String token) {
  133. UserInfo userInfo = getUser(token);
  134. return userInfo.getUserId() != null;
  135. }
  136. // =================== UserInfo缓存相关操作 ===================
  137. /**
  138. * 设置Redis用户数据
  139. */
  140. public static void setLoginUser(UserInfo userInfo) {
  141. StpUtil.getTokenSessionByToken(cutToken(userInfo.getToken())).set(USER_INFO_KEY, userInfo);
  142. }
  143. /**
  144. * 设置本地用户数据
  145. */
  146. public static void setLocalLoginUser(UserInfo userInfo) {
  147. USER_CACHE.set(userInfo);
  148. }
  149. /**
  150. * 获取本地用户数据
  151. */
  152. public static UserInfo getLocalLoginUser() {
  153. return USER_CACHE.get();
  154. }
  155. /**
  156. * 清空本地用户数据
  157. */
  158. public static void clearLocalUser() {
  159. USER_CACHE.remove();
  160. }
  161. /**
  162. * 获取用户缓存
  163. * 保留旧方法
  164. *
  165. * @param token
  166. * @return
  167. */
  168. public UserInfo get(String token) {
  169. return UserProvider.getUser(token);
  170. }
  171. /**
  172. * 获取用户缓存
  173. *
  174. * @return
  175. */
  176. public UserInfo get() {
  177. return UserProvider.getUser();
  178. }
  179. /**
  180. * 根据用户ID, 租户ID获取随机获取一个UserInfo
  181. * @param userId
  182. * @param tenantId
  183. * @return
  184. */
  185. public static UserInfo getUser(String userId, String tenantId){
  186. return getUser(userId, tenantId, null, null);
  187. }
  188. /**
  189. * 根据用户ID, 租户ID, 设备类型获取随机获取一个UserInfo
  190. * @param userId
  191. * @param tenantId
  192. * @param includeDevice 指定的设备类型中查找
  193. * @param excludeDevice 排除指定设备类型
  194. * @return
  195. */
  196. public static UserInfo getUser(String userId, String tenantId, List<String> includeDevice, List<String> excludeDevice){
  197. SaSession session = StpUtil.getSessionByLoginId(splicingLoginId(userId, tenantId), false);
  198. if (session != null) {
  199. List<SaTerminalInfo> tokenSignList = session.getTerminalList();
  200. if (!tokenSignList.isEmpty()) {
  201. tokenSignList = tokenSignList.stream().filter(tokenSign -> {
  202. if(!ObjectUtils.isEmpty(excludeDevice)){
  203. if(excludeDevice.contains(tokenSign.getDeviceType())){
  204. return false;
  205. }
  206. }
  207. if(!ObjectUtils.isEmpty(includeDevice)){
  208. if(!includeDevice.contains(tokenSign.getDeviceType())){
  209. return false;
  210. }
  211. }
  212. return true;
  213. }).collect(Collectors.toList());
  214. if(!tokenSignList.isEmpty()){
  215. return getUser(tokenSignList.get(0).getTokenValue());
  216. }
  217. }
  218. }
  219. return new UserInfo();
  220. }
  221. /**
  222. * 获取用户缓存
  223. *
  224. * @param token
  225. * @return
  226. */
  227. public static UserInfo getUser(String token) {
  228. UserInfo userInfo = null;
  229. String tokens = null;
  230. if (token != null) {
  231. tokens = cutToken(token);
  232. } else {
  233. try {
  234. //处理非Web环境报错
  235. tokens = StpUtil.getTokenValue();
  236. } catch (Exception e) {
  237. }
  238. }
  239. if (tokens != null) {
  240. if (StpUtil.getLoginIdByToken(tokens) != null) {
  241. userInfo = (UserInfo) StpUtil.getTokenSessionByToken(tokens).get(USER_INFO_KEY);
  242. }
  243. }
  244. if (userInfo == null) {
  245. userInfo = new UserInfo();
  246. }
  247. return userInfo;
  248. }
  249. /**
  250. * 获取用户缓存
  251. *
  252. * @return
  253. */
  254. public static UserInfo getUser() {
  255. // if(StpUtil.getTokenValue() == null){
  256. // return new UserInfo();
  257. // }
  258. UserInfo userInfo = USER_CACHE.get();
  259. if (userInfo != null) {
  260. return userInfo;
  261. }
  262. userInfo = UserProvider.getUser(null);
  263. if (userInfo.getUserId() != null) {
  264. USER_CACHE.set(userInfo);
  265. }
  266. return userInfo;
  267. }
  268. // =================== Token相关操作 ===================
  269. /**
  270. * 去除Token前缀
  271. *
  272. * @param token
  273. * @return
  274. */
  275. public static String cutToken(String token) {
  276. if (token != null && token.startsWith(TOKEN_PREFIX_SP)) {
  277. token = token.substring(TOKEN_PREFIX_SP.length());
  278. }
  279. return token;
  280. }
  281. /**
  282. * 获取token
  283. */
  284. public static String getToken() {
  285. String toke = getAuthorize();
  286. return toke;
  287. }
  288. /**
  289. * 获取Authorize
  290. */
  291. public static String getAuthorize() {
  292. String authorize = ServletUtil.getHeader(Constants.AUTHORIZATION);
  293. return authorize;
  294. }
  295. /**
  296. * TOKEN续期
  297. */
  298. public static void renewTimeout(String token) {
  299. if (StpUtil.getTokenValue() != null) {
  300. UserInfo userInfo = UserProvider.getUser(token);
  301. if(userInfo.getUserId() == null || userInfo.getTokenTimeout() == null) {
  302. //避免请求过网关之后TOKEN失效(携带TOKEN调用登录接口之后账号被顶替)
  303. return;
  304. }
  305. StpUtil.renewTimeout(userInfo.getTokenTimeout() * 60L);
  306. if(userInfo.getIsAdministrator()) {
  307. SaSession saSession = StpUtil.getSessionByLoginId(splicingLoginId(Constants.ADMIN_KEY), false);
  308. if (saSession != null) {
  309. saSession.updateTimeout(userInfo.getTokenTimeout() * 60L);
  310. }
  311. }
  312. }
  313. }
  314. /**
  315. * 获取所有Token记录
  316. * 包含无效状态的用户、临时用户
  317. *
  318. * @return
  319. */
  320. public static List<String> getLoginUserListToken() {
  321. return StpUtil.searchTokenValue("", -1, -1, true).stream().map(token -> token.replace(StpUtil.stpLogic.splicingKeyTokenValue(""), "")).collect(Collectors.toList());
  322. }
  323. // =================== 临时Token相关操作 ===================
  324. /**
  325. * 获取内部服务传递验证TOKEN
  326. *
  327. * @return
  328. */
  329. public static String getInnerAuthToken() {
  330. return SaSameUtil.getToken();
  331. }
  332. /**
  333. * 验证内部传递Token是否有效 抛出异常
  334. * @param token
  335. */
  336. public static void checkInnerToken(String token){
  337. SaSameUtil.checkToken(token);
  338. }
  339. /**
  340. * 验证内部传递Token是否有效
  341. * @param token
  342. */
  343. public static boolean isValidInnerToken(String token){
  344. return SaSameUtil.isValid(token);
  345. }
  346. // =================== 退出相关操作 ===================
  347. /**
  348. * 根据用户ID踢出全部用户
  349. * @param userId
  350. */
  351. public static void kickoutByUserId(String userId, String tenantId) {
  352. StpUtil.kickout(splicingLoginId(userId, tenantId));
  353. }
  354. /**
  355. * 根据Token踢出指定会话
  356. * @param tokens
  357. */
  358. public static void kickoutByToken(String... tokens) {
  359. for (String token : tokens) {
  360. StpUtil.kickoutByTokenValue(token);
  361. }
  362. }
  363. /**
  364. * 退出当前Token, 不清除用户其他系统缓存
  365. */
  366. public static void logout() {
  367. StpUtil.logout();
  368. }
  369. /**
  370. * 退出指定Token, 不清除用户其他系统缓存
  371. *
  372. * @param token
  373. */
  374. public static void logoutByToken(String token) {
  375. if (token == null) {
  376. logout();
  377. } else {
  378. StpUtil.logoutByTokenValue(cutToken(token));
  379. }
  380. }
  381. /**
  382. * 退出指定设备类型的用户的全部登录信息, 不清除用户其他系统缓存
  383. *
  384. * @param userId
  385. * @param deviceType
  386. */
  387. public static void logoutByUserId(String userId, DeviceType deviceType) {
  388. StpUtil.logout(splicingLoginId(userId), deviceType.getDevice());
  389. }
  390. /**
  391. * 退出指定用户的全部登录信息, 清除相关缓存
  392. *
  393. * @param userId
  394. */
  395. public static void logoutByUserId(String userId) {
  396. StpUtil.logout(splicingLoginId(userId));
  397. removeOtherCache(userId);
  398. }
  399. // =================== 用户权限 ===================
  400. /**
  401. * 获取当前用户拥有的权限列表(菜单编码列表、功能ID列表)
  402. * @return
  403. */
  404. public static List<String> getPermissionList(){
  405. return StpUtil.getPermissionList();
  406. }
  407. /**
  408. * 获取当前用户拥有的角色列表
  409. * @return
  410. */
  411. public static List<String> getRoleList(){
  412. return StpUtil.getRoleList();
  413. }
  414. // =================== 其他缓存相关操作 ===================
  415. /**
  416. * 移除
  417. */
  418. public static void removeOtherCache(String userId) {
  419. redisUtil.remove(cacheKeyUtil.getUserAuthorize() + userId);
  420. redisUtil.remove(cacheKeyUtil.getSystemInfo());
  421. }
  422. /**
  423. * 是否在线
  424. */
  425. public boolean isOnLine(String userId) {
  426. return StpUtil.getTokenValueByLoginId(splicingLoginId(userId), getDeviceForAgent().getDevice()) != null;
  427. }
  428. /**
  429. * 是否登陆
  430. */
  431. public static boolean isLogined() {
  432. return StpUtil.isLogin();
  433. }
  434. /**
  435. * 指定Token是否有效
  436. * @param token
  437. * @return
  438. */
  439. public static boolean isValid(String token) {
  440. return StpUtil.getLoginIdByToken(token) != null;
  441. }
  442. public static DeviceType getDeviceForAgent() {
  443. if (ServletUtil.getIsMobileDevice()) {
  444. return DeviceType.APP;
  445. } else {
  446. return DeviceType.PC;
  447. }
  448. }
  449. /**
  450. * 判断用户是否是临时用户
  451. * @param userInfo
  452. * @return
  453. */
  454. public static boolean isTempUser(UserInfo userInfo){
  455. if(userInfo == null){
  456. userInfo = getUser();
  457. }
  458. return DeviceType.TEMPUSER.getDevice().equals(userInfo.getLoginDevice())
  459. || DeviceType.TEMPUSERLIMITED.getDevice().equals(userInfo.getLoginDevice());
  460. }
  461. }