package com.matrix.system.app.authority;
|
|
import cn.hutool.crypto.SecureUtil;
|
import cn.hutool.json.JSONArray;
|
import cn.hutool.json.JSONObject;
|
import cn.hutool.json.JSONUtil;
|
import com.matrix.component.redis.RedisClient;
|
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.AuthorityManager;
|
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.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
|
public class AppAuthorityManager implements AuthorityManager {
|
|
private static final int DEFAULT_2 = 2;
|
|
@Autowired
|
RedisClient redisClient;
|
|
@Autowired
|
SysFunctionService sysFunctionService;
|
|
public static final String USER_POWER_REDISKEY = "USER_POWER_";
|
|
public static final String USERFUNCTION = "userFunction";
|
/** 用户所有路径权限的记录 **/
|
public static final String USER_URL_MAPPING = "userUrlMapping";
|
|
private AppAuthorityManager() {
|
}
|
|
public <T> 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) {
|
throw new UnsupportedOperationException("未实现");
|
}
|
|
/**
|
* 判断用户是否具有功能权限
|
* @return
|
*/
|
@Override
|
public boolean isFnPermitted(String fnCode) {
|
throw new UnsupportedOperationException("未实现");
|
}
|
|
/**
|
* 初始化用户权限
|
*
|
* @author JIANGYOUYAO
|
* @email 935090232@qq.com
|
* @date 2017年12月5日
|
* @param result
|
* @param user
|
*/
|
public void initUserPower(AjaxResult result, SysUsers user) {
|
|
// 记录用户所有的功能
|
Map<String, SysFunction> userFunction = new HashMap<>(MatrixConstance.COLLECTION_SIZE);
|
//
|
List<String> userUrlMapping = new ArrayList<>();
|
|
|
String redisKey = USER_POWER_REDISKEY + SecureUtil.md5(user.getSuId()+"");
|
String cachedValue = redisClient.getCachedValue(redisKey);
|
if (StringUtils.isNotBlank(cachedValue)) {
|
//从缓存中获取用户权限
|
JSONObject powerMap = JSONUtil.parseObj(cachedValue);
|
String userFunctionMapStr = powerMap.get(USERFUNCTION).toString();
|
JSONObject userFunctionMap = JSONUtil.parseObj(userFunctionMapStr);
|
Set<String> userFunctionMapKeys = userFunctionMap.keySet();
|
userFunctionMapKeys.forEach(key -> {
|
userFunction.put(key, userFunctionMap.get(key, SysFunction.class));
|
});
|
|
String userUrlMappingListStr = powerMap.get(USER_URL_MAPPING).toString();
|
JSONArray userUrlMappingArray = JSONUtil.parseArray(userUrlMappingListStr);
|
for (int i = 0; i < userUrlMappingArray.size(); i++) {
|
userUrlMapping.add(userUrlMappingArray.get(i, String.class));
|
}
|
} else {
|
// 获取用户所有权限
|
getUserFunction(user,userFunction, userUrlMapping);
|
|
Map<String ,Object> powerMap=new HashMap<>();
|
powerMap.put(USERFUNCTION, userFunction);
|
powerMap.put(USER_URL_MAPPING, userUrlMapping);
|
redisClient.saveValue(redisKey,JSONUtil.parseObj(powerMap,true));
|
}
|
|
|
// TODO 这里的用户权限应该放到redis缓存中,在拦截器中做权限拦截
|
WebUtil.setSessionAttribute(USERFUNCTION, userFunction);
|
WebUtil.setSessionAttribute(USER_URL_MAPPING, userUrlMapping);
|
result.putInMap(USERFUNCTION, userFunction);
|
|
}
|
|
/**
|
* 获取用的功能,包括菜单功能和非菜单功能
|
*
|
* @author JIANGYOUYAO
|
* @email 935090232@qq.com
|
* @date 2017年12月5日
|
* @param userFunctionMap
|
* @param userUrlMapping
|
*/
|
private void getUserFunction(SysUsers sysUser, Map<String, SysFunction> userFunctionMap,
|
List<String> userUrlMapping) {
|
// 判断用户类型
|
if (AppConstance.USER_TYPE_ADMIN.equals(sysUser.getSuUserType())) {
|
// 管理员拥有公司全部权限
|
List<SysFunction> tempList = sysFunctionService.findCompanyFunction(sysUser.getCompanyId());
|
|
// 区分菜单和非菜单功能
|
for (SysFunction sysFunction : tempList) {
|
|
userFunctionMap.put(sysFunction.getFnCode(), sysFunction);
|
// 注册访问路径
|
registerUrlMapping(userUrlMapping, sysFunction,true);
|
}
|
} else if (AppConstance.USER_TYPE_EMPLOYEE.equals(sysUser.getSuUserType())) {
|
// 普通员工账号只拥有自己所拥有的权限
|
List<SysFunction> 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);
|
}
|
}
|
}
|
}
|
|
/**
|
* 注册功能和按钮的访问路径
|
*
|
* @author JIANGYOUYAO
|
* @email 935090232@qq.com
|
* @date 2017年12月8日
|
* @param userUrlMapping
|
* @param sysFunction
|
*/
|
private void registerUrlMapping(List<String> userUrlMapping, SysFunction sysFunction, boolean isAdmin) {
|
String path = sysFunction.getFnPath();
|
if (StringUtils.isNotBlank(path) && !userUrlMapping.contains(path)) {
|
userUrlMapping.add(path);
|
}
|
// 注册按钮路径
|
List<SysFnBtnRel> 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);
|
}
|
}
|
}
|
}
|
}
|
|
/**
|
* 把菜单组装成树形结构
|
*
|
* @author JIANGYOUYAO
|
* @email 935090232@qq.com
|
* @date 2017年12月5日
|
* @param menuFunction
|
* @param menuFunctionMap
|
*/
|
private void assembleMenu(List<SysFunction> menuFunction, Map<String, SysFunction> menuFunctionMap) {
|
// 将map.entrySet()转换成list,并按照功能的FnSequence倒序
|
List<Entry<String, SysFunction>> list = new ArrayList<>(menuFunctionMap.entrySet());
|
Collections.sort(list, new Comparator<Entry<String, SysFunction>>() {
|
@Override
|
public int compare(Entry<String, SysFunction> o1, Entry<String, SysFunction> 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<String, SysFunction> 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<SysFunction> childs = parentFn.getChilds();
|
if (childs == null) {
|
parentFn.setChilds(new ArrayList<SysFunction>());
|
}
|
parentFn.getChilds().add(function);
|
}
|
|
}
|
}
|
}
|
|
}
|