All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.benma666.sjsj.web.UserManager Maven / Gradle / Ivy

/**
 * Project Name:myutils
 * Date:2018年12月19日
 * Copyright (c) 2018, jingma All Rights Reserved.
 */

package cn.benma666.sjsj.web;

import cn.benma666.constants.SysAuth;
import cn.benma666.constants.UtilConst;
import cn.benma666.constants.UtilConstInstance;
import cn.benma666.crypt.DesUtil;
import cn.benma666.dict.Zdlb;
import cn.benma666.domain.SysQxJgxx;
import cn.benma666.domain.SysQxYhxx;
import cn.benma666.domain.SysSjglSjdx;
import cn.benma666.exception.MyException;
import cn.benma666.exception.NotFindUserException;
import cn.benma666.iframe.*;
import cn.benma666.myutils.DateUtil;
import cn.benma666.myutils.StringUtil;
import cn.benma666.sjzt.Db;
import cn.benma666.sjzt.SjsjField;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.beetl.sql.core.SqlId;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;

import java.net.URLEncoder;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 用户管理器 
* date: 2018年12月19日
* @author jingma */ public class UserManager extends BasicObject { /** * 临时用户 */ public static final String LSYH = UtilConst.LSYH; /** * 登陆凭证 */ public static final String TOKEN = "token"; /** * 登陆时间KEY */ public static final String DLSJ = "dlsj"; /** * 全部权限信息缓存 */ protected static final JSONObject authAllCache = CacheFactory.use("authAll", CacheFactory.TYPE_MEMORY); /** * 会话缓存 */ private static final JSONObject hhCache = CacheFactory.use("hhCache"); /** * redis工具 */ private static RedisTemplate redisTemplate; /** * 会话有效期(分钟) */ private static long sessionYxq = 12*60; /** * 用户信息缓存 */ private static final JSONObject userCache = CacheFactory.use(LjqInterface.KEY_USER); public UserManager(RedisTemplate redisTemplate) { UserManager.redisTemplate = redisTemplate; sessionYxq = DateUtil.scSjStrToLong(Conf.getVal("server.servlet.session.timeout", sessionYxq+"m"))/60000; } /** * @return 根据token获取用户 */ public static SysQxYhxx getUser(String token) { MyParams myParams = new MyParams(); myParams.set(UtilConst.$_SYS_TOKEN,token); return getUser(myParams); } /** * 获取用户信息
* * @param myParams 参数 * @return 用户信息,当token为空时返回空 * @author jingma */ public static SysQxYhxx getUser(MyParams myParams) { String token = myParams.getString(LjqInterface.$_SYS_TOKEN); //已经获取过用户了 SysQxYhxx user = myParams.getObject(LjqInterface.KEY_USER,SysQxYhxx.class); if(user==null){ if (StringUtil.isBlank(token)) { //token一般来说一定会有值,没有值为系统内部调用 return null; } synchronized (userCache){ user = userCache.getObject(token,SysQxYhxx.class); } }else { //直接返回 return user; } if(user!=null){ long dlsj = (long) user.get(DLSJ); if(System.currentTimeMillis()-dlsj>sessionYxq*60000){ //过期 synchronized (userCache){ userCache.remove(token); zxhhjy(user); } user = null; }else{ //重置有效期 if(redisTemplate!=null){ redisTemplate.expire(LjqInterface.KEY_USER+":"+token,sessionYxq, TimeUnit.MINUTES); } user.set(DLSJ,System.currentTimeMillis()); } } if(user==null&&redisTemplate!=null){ Object obj = redisTemplate.opsForValue().get(LjqInterface.KEY_USER+":"+token); if(obj != null) { //本系统过期,或本系统第一次访问,其他子系统还在访问的场景 user = (SysQxYhxx) obj; addUser(token,user); } } //实现免登陆,处理带用户信息的url if (user == null || (LSYH.equals(user.getYhdm()) && myParams.getString("$.sys.userInfo") != null)) { //第一次请求或(是临时用户且提供了加密用户信息) return zddl(myParams, token); } return user; } /** * 将用户信息加密,然后重定向到指定url
* @param url 待转发地址 * @param projectCode 项目代码 * @param user 用户标志,默认为用户身份证号,可以采用“yhdm=xxx”的形式传入用户代码进行自动登陆 * @return 带用户信息的地址 * @author jingma */ public static String doDesEncryptUrl(String url, String projectCode, String user){ String token = defaultCache.getString(projectCode + user); if(isBlank(token)){ //避免每次都进行完整的登录 token=StringUtil.getUUIDUpperStr(); defaultCache.put(projectCode + user,token); } String userInfo = enUserinfo(projectCode, user); JSONObject app = DictManager.zdObjByDm(Zdlb.SYS_QX_APP.name(), projectCode); try { url = app.getString("dz") + url; int idx = url.indexOf("?"); if (idx > -1) { //解决url中包含中文参数导致转发后中文信息丢失问题。 StringBuilder url1 = new StringBuilder(url.substring(0, idx + 1)); for (String p : url.substring(idx + 1).split("&")) { String[] pa = p.split("="); url1.append(pa[0]).append("=").append(URLEncoder.encode(pa[1], "utf8")).append("&"); } url = url1.toString(); } else { url += "?"; } url += "sys.userInfo=" + URLEncoder.encode(userInfo, "utf8")+"&sys.token="+token; if(!url.startsWith("http")){ //配置的相对地址则读取配置的统一代理地址进行补充 url = Conf.getUtilConfig().getService().getTydlzd()+url; } return url; } catch (Exception e) { throw new MyException(projectCode+"生成用户信息转发地址失败:" + e.getMessage()); } } /** * 加密用户信息 * @param projectCode 应用代码 * @param user 用户代码 * @return 加密串 */ public static String enUserinfo(String projectCode, String user) { String userInfo; userInfo = DateUtil.getGabDate() + "@" + user; JSONObject app = DictManager.zdObjByDm(Zdlb.SYS_QX_APP.name(), projectCode); if(app ==null){ throw new MyException("该请求的应用不存在:"+ projectCode); } String pwd = app.getString("mm"); if (StringUtil.isBlank(pwd)) { throw new MyException("应用必须设置密码:"+ projectCode); } pwd = DesUtil.decrypt(pwd, Conf.getUtilConfig().getAppEjmm()); userInfo = DesUtil.encrypt(userInfo, pwd).replaceAll("[\n\r]", ""); return userInfo; } /** * 自动登陆
* @param myParams 参数 * @param token 权限认证key * @return 登陆后的用户信息 * @author jingma */ public static SysQxYhxx zddl(MyParams myParams, String token) { SysQxYhxx user = null; Object obj = myParams.get("$.sys.userInfo"); if (!StringUtil.isBlank(obj)) { String userInfo = obj.toString(); if(userInfo.startsWith("sqm-")){ //授权码机制 String sqm = userInfo.substring(4); if(isBlank(sqm)){ throw new MyException("自动登录授权码为空"); } MyParams p = new MyParams(); p.set("$.yobj.sqm", sqm); user = findUser(p,true); }else { JSONObject app = DictManager.zdObjByDm(Zdlb.SYS_QX_APP.name(), Conf.getAppdm()); String pwd = app.getString("mm"); String zddlms = app.getString("zddlms"); if (StringUtil.isBlank(pwd)) { throw new MyException("应用未设置密码", myParams); } try { //解密应用密码 pwd = DesUtil.decrypt(pwd, Conf.getUtilConfig().getAppEjmm()); } catch (Exception e) { throw new MyException("解析用户信息失败:" + userInfo + ">" + e.getMessage(), e); } if ("date_user".equals(zddlms)) { //用户时间加密模式,用户信息解密 userInfo = DesUtil.decrypt(userInfo, pwd); } int idx = userInfo.indexOf("@"); if ("date_user".equals(zddlms)) { //用户时间加密模式,推荐使用 Date urlDate = DateUtil.parseDate(userInfo.substring(0, idx)); assert urlDate != null; if (Math.abs(urlDate.getTime() - new Date().getTime()) > 1000 * 60 * 5) { throw new MyException("用户信息过期:" + userInfo, myParams); } } else if ("pwd_user".equals(zddlms)) { String ipxz = JSON.parseObject(app.getString("kzxx")).getString("ipxz"); if(StringUtil.isBlank(ipxz)){ throw new MyException("一般密码模式自动登陆的应用必须配置ip限制:" + userInfo, myParams); } if(!myParams.getString("$.sys.clientIp").matches(ipxz)){ throw new MyException("请在规定的ip机器上访问:" + userInfo, myParams); } if(!pwd.equals(userInfo.substring(0, idx))){ //明文密码加用户模式,内部调用 throw new MyException("密码不正确:" + userInfo, myParams); } } user = findUser(userInfo.substring(idx + 1)); } slog.info("自动登陆成功:" + user.getSfzh()); } //没有登录时,返回临时用户,后续可以在权限系统中对临时用户进行授权 if (user == null) { synchronized (userCache){ obj = userCache.getString(LSYH); } if(obj==null){ user = findUser(LSYH); addUser(LSYH, user); user = JSON.parseObject(user.toString(),SysQxYhxx.class); }else{ //避免对象复用 user = JSON.parseObject(obj.toString(),SysQxYhxx.class); } } if (StringUtil.isNotBlank(user.getXzip()) && !user.getClientIp().matches(user.getXzip())) { throw new MyException("你未不在授权的ip范围内登录:" + user, myParams); } else { addUser(token, user); } return user; } /** * 添加用户
* @param token 权限码 * @param user 用户信息 * @author jingma */ public static void addUser(String token, SysQxYhxx user) { qcgqyhhc(); if (StringUtil.isNotBlank(token)) { synchronized (userCache){ SysQxYhxx oldUser = userCache.getObject(token, SysQxYhxx.class); if(oldUser==null||!oldUser.getId().equals(user.getId())){ //若当前登录用户不是已经登录的用户 synchronized (hhCache) { int yhhhs = hhCache.getIntValue("yhhhs_" + user.getId()); if (!LSYH.equals(user.getYhdm()) && yhhhs > valByDef(Conf.getUtilConfig().getLogin().getTszxhhsxz(), 20)) { throw new MyException("你同时在线会话数超过系统限制"); } //对该用户在线会话计数 hhCache.put("yhhhs_" + user.getId(), yhhhs + 1); } } user.setToken(token); //设置登陆时间 user.set(DLSJ,System.currentTimeMillis()); userCache.put(token,user); if(redisTemplate!=null){ redisTemplate.opsForValue().set(LjqInterface.KEY_USER+":"+token, user, sessionYxq, TimeUnit.MINUTES); } } } else { slog.debug("权限码为空:" + user); } } /** * 移除登陆的用户,用户登陆退出
* * @param user 要移除的用户 * @return 处理结果 * @author jingma */ public static Result removeUser(SysQxYhxx user) { if(redisTemplate!=null){ redisTemplate.delete(LjqInterface.KEY_USER+":"+user.getToken()); } synchronized (userCache){ userCache.remove(user.getToken()); zxhhjy(user); } return success("退出成功"); } public static SysQxYhxx findUser(String userStr) { return findUser(userStr,true); } /** * 获取用户信息 * @param userStr 用户信息字符串,支持id、身份证、代码、微信id * @return 用户完整信息 */ @NotNull public static SysQxYhxx findUser(String userStr,boolean cache) { if (userStr.startsWith("yhdm=")) { userStr = userStr.substring(5); } else if (userStr.startsWith("id=")) { userStr = userStr.substring(3); } MyParams myParams = new MyParams(); myParams.set("$.yobj.yhdm", userStr); return findUser(myParams,cache); } /** * 获取用户的完整信息,包括基础信息、机构、权限
* * @param myParams 参数集合 * @return 用户信息 * @author jingma */ public static SysQxYhxx findUser(MyParams myParams,boolean cache) throws MyException { SysQxYhxx yobj = myParams.yobj(SysQxYhxx.class); //设置终端类别,不同终端权限不一样,有些功能手机端不支持 yobj.setZdlb(myParams.sys().getZdlb()); Object o = defaultCache.get(yobj.toString()); if(o!=null&&cache){ return (SysQxYhxx) o; } //查询用户 SysQxYhxx user; user = Db.useSqlManager().selectSingle(SqlId.of("sjsj", "findUser"), myParams, SysQxYhxx.class); if(user==null){ throw new NotFindUserException("没有找到用户:"+yobj); } user.setZdlb(myParams.sys().getZdlb()); //查询机构 SysQxJgxx jgxx = Db.use().lambdaQuery(SysQxJgxx.class).andEq(SysQxJgxx::getId,user.getSsjg()).singleSimple(); if(jgxx==null){ throw new MyException("没有找到用户的机构:"+user); } user.setJgxx(jgxx); loadYhqx(user); if(cache){ defaultCache.put(yobj.toString(),user); } return user; } /** * 刷新用户权限信息
* * @author jingma * @param myParams 参数对象 */ public static void flushUserQxxx(MyParams myParams) { SysQxYhxx user; synchronized (userCache){ if(redisTemplate!=null){ //使用redis final Cursor scan = redisTemplate.scan(ScanOptions.scanOptions().match("user*").build()); while (scan.hasNext()){ final String key = scan.next(); user = ((SysQxYhxx) redisTemplate.opsForValue().get(key)); assert user != null; loadYhqx(user); userCache.put(user.getToken(),user); redisTemplate.opsForValue().set(key,user,sessionYxq, TimeUnit.MINUTES); } }else{ //不使用redis for (String key : userCache.keySet()) { user = userCache.getObject(key,SysQxYhxx.class); loadYhqx(user); userCache.put(key,user); } } } } /** * 清除过期用户缓存 */ private static void qcgqyhhc(){ SysQxYhxx user; long dlsj; synchronized (userCache){ Iterator> uc = userCache.entrySet().iterator(); while (uc.hasNext()) { Map.Entry e = uc.next(); user = (SysQxYhxx) e.getValue(); dlsj = (long) user.get(DLSJ); if(System.currentTimeMillis()-dlsj>sessionYxq*60000){ zxhhjy(user); //过期 uc.remove(); } } } } /** * 用户在线会话减一 * @param user 用户信息 */ private static void zxhhjy(SysQxYhxx user){ //该用户会话数减一 synchronized (hhCache){ hhCache.put("yhhhs_"+user.getId(),hhCache.getIntValue("yhhhs_"+user.getId())-1); } } /** * 加载用户权限相关信息:角色、权限、对象代码与权限的映射 */ private static void loadYhqx(SysQxYhxx user){ JSONObject params = Db.buildKeyMap(UtilConstInstance.KEY_USER, user); //查询角色 user.setJsMap(Db.use().findMap("js",SqlId.of("sjsj","findJsxx"),params)); //设置用户权限 user.setQxMap(Db.use().findMap("dm", SqlId.of("sjsj","findYhqxxx"), params)); //设置用户相关对象与权限代码的映射关系 user.setDxqxys(Db.use().findMap("dxdm", SqlId.of("sjsj","findYhDxQxYs"), params)); //设置登陆时间,计算会话超时 user.set(DLSJ,System.currentTimeMillis()); } public static boolean hasAuth(MyParams myParams){ return hasAuth(myParams,myParams.sys().getCllx()); } public static boolean hasAuth(MyParams myParams,String cllx){ return hasAuth(myParams.user(),myParams.sys().getAuthCode(),cllx, myParams.sjdx(),myParams.sys().getNbdy()); } public static boolean hasAuth(SysQxYhxx user,String authCode,String cllx){ return hasAuth(user,authCode+"_"+cllx); } public static boolean hasAuth(SysQxYhxx user,String qxm){ return hasAuth(user,qxm,null,false); } public static boolean hasAuthByUser(JSONObject user,String qxm){ return hasAuth(user.toJavaObject(SysQxYhxx.class),qxm,null,false); } public static boolean hasAuth(SysQxYhxx user,String authCode,String cllx,SysSjglSjdx sjdx,boolean nbdy) { if (authCode == null) { //没有配置权限时则统一采用未授权对象的权限 authCode = SysAuth.QTQX_WSQDX.name(); } //最终权限码 String qxm = authCode + "_" + cllx; return hasAuth(user, qxm, sjdx, nbdy); } public static boolean hasAuth(SysQxYhxx user,String qxm,SysSjglSjdx sjdx,boolean nbdy){ //有权限 boolean yqx = false; if (nbdy||user==null||user.getQxMap().containsKey(SysAuth.QTQX_SYS.name())) { //内部调用或内部调用没有用户或拥有最高权限,则默认通过。 yqx = true; }else{ synchronized (authAllCache){ if(authAllCache.isEmpty()){ //权限缓存为空则读取权限信息并缓存 authAllCache.putAll(Db.use().findMap("dm", SqlId.of("sjsj", "findYhqxxx"), Db.buildMap())); } } //没有配置权限的接口登陆用户可以直接访问,配置了权限的接口必须授权才能访问 if(!authAllCache.containsKey(qxm)&&!UtilConst.LSYH.equals(user.getYhdm())){ yqx = true; }else if (user.getQxMap().containsKey(qxm)) { //对象权限判断 yqx = true; } String sqms = valByDef(Conf.getUtilConfig().getXtqxSqms(), SjsjField.cllx.name()); switch (sqms){ case "sjdx": if(!yqx&&sjdx!=null){ //数据对象不为空,为空则走处理类型校验 yqx = user.getDxqxys().containsKey(sjdx.getDxdm()); } break; case "cllx": break; default: throw new MyException("暂不支持该授权模式:"+sqms); } } return yqx; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy