package com.matrix.system.common.authority; import cn.hutool.crypto.SecureUtil; import com.matrix.core.constance.MatrixConstance; import com.matrix.core.pojo.AjaxResult; import com.matrix.core.tools.StringUtils; import com.matrix.core.tools.WebUtil; import com.matrix.system.common.authority.strategy.LoginStrategy; import com.matrix.system.common.bean.SysFnBtnRel; import com.matrix.system.common.bean.SysFunction; import com.matrix.system.common.bean.SysUsers; import com.matrix.system.common.constance.AppConstance; import com.matrix.system.common.init.LocalCache; import com.matrix.system.common.service.SysFunctionService; import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.*; import java.util.Map.Entry; /** * DefaultAuthorityManager 实现了权限控制接口 * * @author JIANGYOUYAO * @email 935090232@qq.com * @date 2017年12月6日 */ @Component("defaultAuthorityManager") public class DefaultAuthorityManager implements AuthorityManager { private static final int DEFAULT_2 = 2; public static final String USER_POWER_REDISKEY = "USER_POWER_"; public static final String USER_POWER_REDISKEY_PC = "USER_POWER_PC"; @Autowired SysFunctionService sysFunctionService; public static final String USERFUNCTION = "userFunction"; public static final String MENUSFUNCTION = "menusFunction"; /** * 用户所有路径权限的记录 **/ public static final String USER_URL_MAPPING = "userUrlMapping"; private DefaultAuthorityManager() { } public T login(LoginStrategy loginStrategy) { @SuppressWarnings("unchecked") T user = (T) loginStrategy.login(); WebUtil.setSessionAttribute(MatrixConstance.LOGIN_KEY, user); WebUtil.setSessionAttribute(AppConstance.DEFAULT_AUTHORITYMANAGER, this); return user; } @Override public void getLoginOut() { WebUtil.getSession().removeAttribute(MatrixConstance.LOGIN_KEY); } /** * 判断用户是否具有按钮功能 * * @param matchStr * @return * @throws IllegalArgumentException */ @Override public boolean isBtnPermitted(String matchStr) { // 开发人员和超级管理员具有所有权限 SysUsers user = WebUtil.getSessionAttribute(MatrixConstance.LOGIN_KEY); Map userFunction = WebUtil.getSessionAttribute(USERFUNCTION); // 企业管理员不校验按钮权限 if (AppConstance.USER_TYPE_DEVELOPER.equals(user.getSuUserType()) || AppConstance.USER_TYPE_SUPER.equals(user.getSuUserType()) || AppConstance.USER_TYPE_ADMIN.equals(user.getSuUserType())) { return true; } if (userFunction == null) { return false; } else { String[] strs = matchStr.split("-"); if (strs.length != DEFAULT_2) { throw new IllegalArgumentException("权限matchStr格式错误,需要fnCode:btnValue"); } SysFunction fn = userFunction.get(strs[0].trim()); // 功能是否存在 if (fn == null) { return false; } else { return StringUtils.isContentSet(strs[1].trim(), fn.getRpfBns()); } } } /** * 判断用户是否具有功能权限 * * @return */ @Override public boolean isFnPermitted(String fnCode) { // 开发人员和超级管理员具有所有权限 SysUsers user = WebUtil.getSessionAttribute(MatrixConstance.LOGIN_KEY); if (AppConstance.USER_TYPE_DEVELOPER.equals(user.getSuUserType()) || AppConstance.USER_TYPE_SUPER.equals(user.getSuUserType())) { return true; } Map userFunction = WebUtil.getSessionAttribute(USERFUNCTION); if (userFunction == null) { return false; } else { SysFunction fn = userFunction.get(fnCode); return fn == null ? false : true; } } /** * 初始化用户权限 * * @param result * @author JIANGYOUYAO * @email 935090232@qq.com * @date 2017年12月5日 */ public void initUserPower(AjaxResult result) { // 记录用户所有的功能 Map userFunction = new HashMap<>(MatrixConstance.COLLECTION_SIZE); // 用户的一级菜单权限 List menuFunction = new ArrayList<>(); // List userUrlMapping = new ArrayList<>(); // 用户的所有功能权限用id记录,方便后面查询菜单树形结构 Map menuFunctionMap = new TreeMap<>(); SysUsers sysUser = WebUtil.getSessionAttribute(MatrixConstance.LOGIN_KEY); String redisKey = USER_POWER_REDISKEY_PC + SecureUtil.md5(sysUser.getSuId() + ""); Map cachePowerMap = LocalCache.get(redisKey); if (Objects.nonNull(cachePowerMap)) { userFunction = (Map) cachePowerMap.get(USERFUNCTION); menuFunction = (List) cachePowerMap.get(MENUSFUNCTION); userUrlMapping = (List) cachePowerMap.get(USER_URL_MAPPING); } else { // 获取用户所有权限 getUserFunction(userFunction, menuFunctionMap, userUrlMapping); // 组装菜单 assembleMenu(menuFunction, menuFunctionMap); Map powerMap = new HashMap<>(); powerMap.put(USERFUNCTION, userFunction); powerMap.put(MENUSFUNCTION, menuFunction); powerMap.put(USER_URL_MAPPING, userUrlMapping); //权限信息加入缓存中 LocalCache.save(redisKey,powerMap); } // 把用户菜单和用户的功能都存在session中。 WebUtil.setSessionAttribute(USERFUNCTION, userFunction); WebUtil.setSessionAttribute(MENUSFUNCTION, menuFunction); WebUtil.setSessionAttribute(USER_URL_MAPPING, userUrlMapping); result.putInMap(USERFUNCTION, userFunction); result.putInMap(MENUSFUNCTION, menuFunction); } /** * 获取用的功能,包括菜单功能和非菜单功能 * * @param userFunctionMap * @param menuFunctionMap * @param userUrlMapping * @author JIANGYOUYAO * @email 935090232@qq.com * @date 2017年12月5日 */ private void getUserFunction(Map userFunctionMap, Map menuFunctionMap, List userUrlMapping) { SysUsers sysUser = WebUtil.getSessionAttribute(MatrixConstance.LOGIN_KEY); // 判断用户类型 if (AppConstance.USER_TYPE_ADMIN.equals(sysUser.getSuUserType())) { // 管理员拥有公司全部权限 List tempList = sysFunctionService.findCompanyFunction(sysUser.getCompanyId()); // 区分菜单和非菜单功能 for (SysFunction sysFunction : tempList) { userFunctionMap.put(sysFunction.getFnCode(), sysFunction); // 注册访问路径 registerUrlMapping(userUrlMapping, sysFunction, true); // 如果是菜单功能单独记录 if (AppConstance.IS_Y.equals(sysFunction.getFnShowMenu())) { menuFunctionMap.put(sysFunction.getFnId() + "", sysFunction); } } } else if (AppConstance.USER_TYPE_EMPLOYEE.equals(sysUser.getSuUserType())) { // 普通员工账号只拥有自己所拥有的权限 List userFunctionList = sysFunctionService.findFunctionByRoleIds(sysUser.getRoleIds()); for (SysFunction sysFunction : userFunctionList) { // TODO注册访问路径 registerUrlMapping(userUrlMapping, sysFunction, false); if (userFunctionMap.containsKey(sysFunction.getFnCode())) { // 如果功能已经被添加到集合中则追加权限按钮 SysFunction oneFunctionInMap = userFunctionMap.get(sysFunction.getFnCode()); // 为了方便判断所以用字符串记录一下 if (StringUtils.isBlank(oneFunctionInMap.getRpfBns())) { oneFunctionInMap.setRpfBns(sysFunction.getRpfBns()); } else { oneFunctionInMap.setRpfBns(oneFunctionInMap.getRpfBns() + "," + sysFunction.getRpfBns()); } } else { // 如果是新功能则直接添加 userFunctionMap.put(sysFunction.getFnCode(), sysFunction); if (AppConstance.IS_Y.equals(sysFunction.getFnShowMenu())) { menuFunctionMap.put(sysFunction.getFnId() + "", sysFunction); } } } } } /** * 注册功能和按钮的访问路径 * * @param userUrlMapping * @param sysFunction * @author JIANGYOUYAO * @email 935090232@qq.com * @date 2017年12月8日 */ private void registerUrlMapping(List userUrlMapping, SysFunction sysFunction, boolean isAdmin) { String path = sysFunction.getFnPath(); if (StringUtils.isNotBlank(path) && !userUrlMapping.contains(path)) { userUrlMapping.add(path); } // 注册按钮路径 List btnRels = sysFunction.getSysFnBtnRel(); if (CollectionUtils.isNotEmpty(btnRels)) { for (SysFnBtnRel sysFnBtnRel : btnRels) { //公司管理员可以添加所有按钮权限否则只能添加员工自己所有拥有的权限 if (isAdmin || StringUtils.isContentSet(sysFnBtnRel.getBtnValue(), sysFunction.getRpfBns())) { String btnPath = sysFnBtnRel.getFbPath(); if (StringUtils.isNotBlank(btnPath) && !userUrlMapping.contains(btnPath)) { userUrlMapping.add(btnPath); } } } } } /** * 把菜单组装成树形结构 * * @param menuFunction * @param menuFunctionMap * @author JIANGYOUYAO * @email 935090232@qq.com * @date 2017年12月5日 */ private void assembleMenu(List menuFunction, Map menuFunctionMap) { // 将map.entrySet()转换成list,并按照功能的FnSequence倒序 List> list = new ArrayList<>(menuFunctionMap.entrySet()); Collections.sort(list, new Comparator>() { @Override public int compare(Entry o1, Entry o2) { Integer a = o1.getValue().getFnSequence() == null ? 0 : o1.getValue().getFnSequence(); Integer b = o2.getValue().getFnSequence() == null ? 0 : o2.getValue().getFnSequence(); return Integer.compare(b, a); } }); // 获取菜单权限,思路:如果遍历map如果功能存在父节点,就找到父节点然后把子节点加入进去,这样就只需要遍历一次 for (Entry entry : list) { String id = entry.getKey(); SysFunction function = menuFunctionMap.get(id); // 如果是一级节点则直接存入菜单 if (null == function.getFnParentId() || 0L == function.getFnParentId()) { menuFunction.add(function); } else { // 非一级节点找到父节点后存入 SysFunction parentFn = menuFunctionMap.get(String.valueOf(function.getFnParentId())); if (parentFn != null) { List childs = parentFn.getChilds(); if (childs == null) { parentFn.setChilds(new ArrayList()); } parentFn.getChilds().add(function); } } } } }