修改用户缓存结构.

This commit is contained in:
lijiahangmax
2023-11-21 00:39:15 +08:00
parent 6c056cecff
commit 8fe105fc8a
14 changed files with 108 additions and 72 deletions

View File

@@ -35,6 +35,6 @@ public class LoginUser {
private Long timestamp; private Long timestamp;
@Schema(description = "角色") @Schema(description = "角色")
private List<String> roles; private List<UserRole> roles;
} }

View File

@@ -0,0 +1,28 @@
package com.orion.ops.framework.common.security;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
/**
* 用户角色
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/11/20 23:39
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Schema(name = "UserRole", description = "用户角色")
public class UserRole {
@EqualsAndHashCode.Include
@Schema(description = "id")
private Long id;
@Schema(description = "角色")
private String code;
}

View File

@@ -22,7 +22,7 @@ public interface PermissionService {
* *
* @return cache * @return cache
*/ */
Map<String, SystemRoleDO> getRoleCache(); Map<Long, SystemRoleDO> getRoleCache();
/** /**
* 获取 菜单缓存 以作角色权限直接引用 * 获取 菜单缓存 以作角色权限直接引用
@@ -36,7 +36,7 @@ public interface PermissionService {
* *
* @return cache * @return cache
*/ */
Map<String, List<SystemMenuCacheDTO>> getRoleMenuCache(); Map<Long, List<SystemMenuCacheDTO>> getRoleMenuCache();
/** /**
* 初始化权限缓存 * 初始化权限缓存

View File

@@ -40,9 +40,9 @@ public interface SystemUserRoleService {
/** /**
* 删除用户缓存中的角色 * 删除用户缓存中的角色
* *
* @param roleCode roleCode * @param roleId roleId
* @param userIdList userIdList * @param userIdList userIdList
*/ */
void deleteUserCacheRoleAsync(String roleCode, List<Long> userIdList); void deleteUserCacheRoleAsync(Long roleId, List<Long> userIdList);
} }

View File

@@ -10,6 +10,7 @@ import com.orion.ops.framework.biz.operator.log.core.uitls.OperatorLogs;
import com.orion.ops.framework.common.constant.Const; import com.orion.ops.framework.common.constant.Const;
import com.orion.ops.framework.common.constant.ErrorMessage; import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.common.security.LoginUser; import com.orion.ops.framework.common.security.LoginUser;
import com.orion.ops.framework.common.security.UserRole;
import com.orion.ops.framework.common.utils.CryptoUtils; import com.orion.ops.framework.common.utils.CryptoUtils;
import com.orion.ops.framework.common.utils.IpUtils; import com.orion.ops.framework.common.utils.IpUtils;
import com.orion.ops.framework.common.utils.Valid; import com.orion.ops.framework.common.utils.Valid;
@@ -20,7 +21,6 @@ import com.orion.ops.module.infra.convert.SystemUserConvert;
import com.orion.ops.module.infra.dao.SystemUserDAO; import com.orion.ops.module.infra.dao.SystemUserDAO;
import com.orion.ops.module.infra.dao.SystemUserRoleDAO; import com.orion.ops.module.infra.dao.SystemUserRoleDAO;
import com.orion.ops.module.infra.define.cache.UserCacheKeyDefine; import com.orion.ops.module.infra.define.cache.UserCacheKeyDefine;
import com.orion.ops.module.infra.entity.domain.SystemRoleDO;
import com.orion.ops.module.infra.entity.domain.SystemUserDO; import com.orion.ops.module.infra.entity.domain.SystemUserDO;
import com.orion.ops.module.infra.entity.dto.LoginTokenDTO; import com.orion.ops.module.infra.entity.dto.LoginTokenDTO;
import com.orion.ops.module.infra.entity.dto.LoginTokenIdentityDTO; import com.orion.ops.module.infra.entity.dto.LoginTokenIdentityDTO;
@@ -289,16 +289,16 @@ public class AuthenticationServiceImpl implements AuthenticationService {
Long id = user.getId(); Long id = user.getId();
// 查询用户角色 // 查询用户角色
List<Long> roleIds = systemUserRoleDAO.selectRoleIdByUserId(id); List<Long> roleIds = systemUserRoleDAO.selectRoleIdByUserId(id);
List<String> roleCodeList = permissionService.getRoleCache() List<UserRole> roleList = permissionService.getRoleCache()
.values() .values()
.stream() .stream()
.filter(s -> roleIds.contains(s.getId())) .filter(s -> roleIds.contains(s.getId()))
.map(SystemRoleDO::getCode) .map(r -> new UserRole(r.getId(), r.getCode()))
.collect(Collectors.toList()); .collect(Collectors.toList());
// 设置用户缓存 // 设置用户缓存
String userInfoKey = UserCacheKeyDefine.USER_INFO.format(id); String userInfoKey = UserCacheKeyDefine.USER_INFO.format(id);
LoginUser loginUser = SystemUserConvert.MAPPER.toLoginUser(user); LoginUser loginUser = SystemUserConvert.MAPPER.toLoginUser(user);
loginUser.setRoles(roleCodeList); loginUser.setRoles(roleList);
RedisStrings.setJson(userInfoKey, UserCacheKeyDefine.USER_INFO, loginUser); RedisStrings.setJson(userInfoKey, UserCacheKeyDefine.USER_INFO, loginUser);
return loginUser; return loginUser;
} }

View File

@@ -4,6 +4,7 @@ import com.orion.lang.utils.Arrays1;
import com.orion.lang.utils.collect.Lists; import com.orion.lang.utils.collect.Lists;
import com.orion.ops.framework.common.constant.Const; import com.orion.ops.framework.common.constant.Const;
import com.orion.ops.framework.common.security.LoginUser; import com.orion.ops.framework.common.security.LoginUser;
import com.orion.ops.framework.common.security.UserRole;
import com.orion.ops.framework.security.core.utils.SecurityUtils; import com.orion.ops.framework.security.core.utils.SecurityUtils;
import com.orion.ops.module.infra.convert.SystemMenuConvert; import com.orion.ops.module.infra.convert.SystemMenuConvert;
import com.orion.ops.module.infra.convert.SystemUserConvert; import com.orion.ops.module.infra.convert.SystemUserConvert;
@@ -51,13 +52,13 @@ import java.util.stream.Stream;
public class PermissionServiceImpl implements PermissionService { public class PermissionServiceImpl implements PermissionService {
@Getter @Getter
private final Map<String, SystemRoleDO> roleCache = new HashMap<>(); private final Map<Long, SystemRoleDO> roleCache = new HashMap<>();
@Getter @Getter
private final List<SystemMenuCacheDTO> menuCache = new ArrayList<>(); private final List<SystemMenuCacheDTO> menuCache = new ArrayList<>();
@Getter @Getter
private final Map<String, List<SystemMenuCacheDTO>> roleMenuCache = new HashMap<>(); private final Map<Long, List<SystemMenuCacheDTO>> roleMenuCache = new HashMap<>();
@Resource @Resource
private SystemRoleDAO systemRoleDAO; private SystemRoleDAO systemRoleDAO;
@@ -87,10 +88,8 @@ public class PermissionServiceImpl implements PermissionService {
roleMenuCache.clear(); roleMenuCache.clear();
// 加载所有角色 // 加载所有角色
List<SystemRoleDO> roles = systemRoleDAO.selectList(null); List<SystemRoleDO> roles = systemRoleDAO.selectList(null);
Map<Long, SystemRoleDO> roleRel = roles.stream()
.collect(Collectors.toMap(SystemRoleDO::getId, Function.identity()));
for (SystemRoleDO role : roles) { for (SystemRoleDO role : roles) {
roleCache.put(role.getCode(), role); roleCache.put(role.getId(), role);
} }
// 加载所有菜单信息 // 加载所有菜单信息
List<SystemMenuDO> menuList = systemMenuDAO.selectList(null); List<SystemMenuDO> menuList = systemMenuDAO.selectList(null);
@@ -103,17 +102,14 @@ public class PermissionServiceImpl implements PermissionService {
.stream() .stream()
.collect(Collectors.groupingBy(SystemRoleMenuDO::getRoleId, .collect(Collectors.groupingBy(SystemRoleMenuDO::getRoleId,
Collectors.mapping(SystemRoleMenuDO::getMenuId, Collectors.toList()))) Collectors.mapping(SystemRoleMenuDO::getMenuId, Collectors.toList())))
.forEach((rid, mids) -> { .forEach((roleId, menuIdList) -> {
// 获取菜单引用 // 获取菜单引用
List<SystemMenuCacheDTO> roleMenus = mids.stream() List<SystemMenuCacheDTO> roleMenus = menuIdList.stream()
.map(menuMapping::get) .map(menuMapping::get)
.filter(Objects::nonNull) .filter(Objects::nonNull)
.collect(Collectors.toList()); .collect(Collectors.toList());
// 获取角色引用 // 获取角色引用
Optional.ofNullable(rid) roleMenuCache.put(roleId, roleMenus);
.map(roleRel::get)
.map(SystemRoleDO::getCode)
.ifPresent(code -> roleMenuCache.put(code, roleMenus));
}); });
log.info("initPermissionCache-end used: {}ms", System.currentTimeMillis() - start); log.info("initPermissionCache-end used: {}ms", System.currentTimeMillis() - start);
} }
@@ -121,7 +117,7 @@ public class PermissionServiceImpl implements PermissionService {
@Override @Override
public boolean hasRole(String role) { public boolean hasRole(String role) {
// 获取用户角色 // 获取用户角色
List<String> roles = this.getUserEnabledRoles(); List<String> roles = this.getUserEnabledRoleCode();
if (roles.isEmpty()) { if (roles.isEmpty()) {
return false; return false;
} }
@@ -132,7 +128,7 @@ public class PermissionServiceImpl implements PermissionService {
@Override @Override
public boolean hasPermission(String permission) { public boolean hasPermission(String permission) {
// 获取用户角色 // 获取用户角色
List<String> roles = this.getUserEnabledRoles(); List<String> roles = this.getUserEnabledRoleCode();
if (roles.isEmpty()) { if (roles.isEmpty()) {
return false; return false;
} }
@@ -150,7 +146,7 @@ public class PermissionServiceImpl implements PermissionService {
return true; return true;
} }
// 获取用户角色 // 获取用户角色
List<String> roles = this.getUserEnabledRoles(); List<String> roles = this.getUserEnabledRoleCode();
if (roles.isEmpty()) { if (roles.isEmpty()) {
return false; return false;
} }
@@ -170,7 +166,7 @@ public class PermissionServiceImpl implements PermissionService {
@Override @Override
public List<SystemMenuVO> getUserMenuList() { public List<SystemMenuVO> getUserMenuList() {
// 获取用户角色 // 获取用户角色
List<String> roles = this.getUserEnabledRoles(); List<String> roles = this.getUserEnabledRoleCode();
if (roles.isEmpty()) { if (roles.isEmpty()) {
return Lists.empty(); return Lists.empty();
} }
@@ -206,7 +202,7 @@ public class PermissionServiceImpl implements PermissionService {
// 获取用户系统偏好 // 获取用户系统偏好
Future<Map<String, Object>> systemPreference = preferenceService.getPreferenceAsync(id, PreferenceTypeEnum.SYSTEM); Future<Map<String, Object>> systemPreference = preferenceService.getPreferenceAsync(id, PreferenceTypeEnum.SYSTEM);
// 获取用户角色 // 获取用户角色
List<String> roles = this.getUserEnabledRoles(); List<String> roles = this.getUserEnabledRoleCode();
// 获取用户权限 // 获取用户权限
List<String> permissions; List<String> permissions;
if (roles.isEmpty()) { if (roles.isEmpty()) {
@@ -266,32 +262,27 @@ public class PermissionServiceImpl implements PermissionService {
* *
* @return roles * @return roles
*/ */
private List<String> getUserEnabledRoles() { private List<String> getUserEnabledRoleCode() {
// 获取当前用户角色 // 获取当前用户角色
List<String> roles = Optional.ofNullable(SecurityUtils.getLoginUser()) List<UserRole> userRoles = Optional.ofNullable(SecurityUtils.getLoginUser())
.map(LoginUser::getRoles) .map(LoginUser::getRoles)
.orElse(Lists.empty()); .orElse(null);
if (Lists.isEmpty(roles)) { if (Lists.isEmpty(userRoles)) {
return Lists.empty(); return Lists.empty();
} }
// 过滤未启用的角色 // 获取角色编码
return roles.stream() List<String> roleCodes = userRoles.stream()
.filter(this::checkRoleEnabled) .map(UserRole::getId)
.map(roleCache::get)
.filter(Objects::nonNull)
// 过滤未启用的角色
.filter(r -> RoleStatusEnum.ENABLED.getStatus().equals(r.getStatus()))
.map(SystemRoleDO::getCode)
.collect(Collectors.toList()); .collect(Collectors.toList());
} if (Lists.isEmpty(roleCodes)) {
return Lists.empty();
/**
* 检查角色是否启用
*
* @param role role
* @return 是否启用
*/
private boolean checkRoleEnabled(String role) {
SystemRoleDO systemRole = roleCache.get(role);
if (systemRole == null) {
return false;
} }
return RoleStatusEnum.ENABLED.getStatus().equals(systemRole.getStatus()); return roleCodes;
} }
} }

View File

@@ -104,12 +104,8 @@ public class SystemRoleMenuServiceImpl implements SystemRoleMenuService {
effect += insertMenuIdList.size(); effect += insertMenuIdList.size();
} }
// 更新缓存 // 更新缓存
Map<String, List<SystemMenuCacheDTO>> cache = permissionService.getRoleMenuCache(); Map<Long, List<SystemMenuCacheDTO>> cache = permissionService.getRoleMenuCache();
List<SystemMenuCacheDTO> roleCache = cache.get(role.getCode()); List<SystemMenuCacheDTO> roleCache = cache.computeIfAbsent(roleId, s -> new ArrayList<>());
if (Lists.isEmpty(roleCache)) {
roleCache = new ArrayList<>();
cache.put(role.getCode(), roleCache);
}
roleCache.clear(); roleCache.clear();
roleCache.addAll(SystemMenuConvert.MAPPER.toCache(menuList)); roleCache.addAll(SystemMenuConvert.MAPPER.toCache(menuList));
return effect; return effect;

View File

@@ -67,7 +67,7 @@ public class SystemRoleServiceImpl implements SystemRoleService {
int effect = systemRoleDAO.insert(record); int effect = systemRoleDAO.insert(record);
log.info("SystemRoleService-createSystemRole effect: {}, domain: {}", effect, JSON.toJSONString(record)); log.info("SystemRoleService-createSystemRole effect: {}, domain: {}", effect, JSON.toJSONString(record));
// 设置到缓存 // 设置到缓存
permissionService.getRoleCache().put(record.getCode(), record); permissionService.getRoleCache().put(record.getId(), record);
return record.getId(); return record.getId();
} }
@@ -87,7 +87,7 @@ public class SystemRoleServiceImpl implements SystemRoleService {
int effect = systemRoleDAO.updateById(updateRecord); int effect = systemRoleDAO.updateById(updateRecord);
log.info("SystemRoleService-updateSystemRoleById effect: {}, updateRecord: {}", effect, JSON.toJSONString(updateRecord)); log.info("SystemRoleService-updateSystemRoleById effect: {}, updateRecord: {}", effect, JSON.toJSONString(updateRecord));
// 设置到缓存 // 设置到缓存
SystemRoleDO roleCache = permissionService.getRoleCache().get(record.getCode()); SystemRoleDO roleCache = permissionService.getRoleCache().get(id);
roleCache.setName(updateRecord.getName()); roleCache.setName(updateRecord.getName());
return effect; return effect;
} }
@@ -112,7 +112,7 @@ public class SystemRoleServiceImpl implements SystemRoleService {
int effect = systemRoleDAO.updateById(updateRecord); int effect = systemRoleDAO.updateById(updateRecord);
log.info("SystemRoleService-updateRoleStatus effect: {}, updateRecord: {}", effect, JSON.toJSONString(updateRecord)); log.info("SystemRoleService-updateRoleStatus effect: {}, updateRecord: {}", effect, JSON.toJSONString(updateRecord));
// 修改缓存状态 // 修改缓存状态
SystemRoleDO roleCache = permissionService.getRoleCache().get(record.getCode()); SystemRoleDO roleCache = permissionService.getRoleCache().get(id);
roleCache.setStatus(status); roleCache.setStatus(status);
return effect; return effect;
} }
@@ -173,11 +173,11 @@ public class SystemRoleServiceImpl implements SystemRoleService {
// 删除角色菜单关联 // 删除角色菜单关联
effect += systemRoleMenuDAO.deleteByRoleId(id); effect += systemRoleMenuDAO.deleteByRoleId(id);
// 删除角色缓存 // 删除角色缓存
permissionService.getRoleCache().remove(code); permissionService.getRoleCache().remove(id);
// 删除菜单缓存 // 删除菜单缓存
permissionService.getRoleMenuCache().remove(code); permissionService.getRoleMenuCache().remove(id);
// 删除用户缓存中的角色 // 删除用户缓存中的角色
systemUserRoleService.deleteUserCacheRoleAsync(code, userIdList); systemUserRoleService.deleteUserCacheRoleAsync(id, userIdList);
return effect; return effect;
} }

View File

@@ -4,6 +4,7 @@ import com.orion.lang.utils.collect.Lists;
import com.orion.ops.framework.biz.operator.log.core.uitls.OperatorLogs; import com.orion.ops.framework.biz.operator.log.core.uitls.OperatorLogs;
import com.orion.ops.framework.common.constant.ErrorMessage; import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.common.security.LoginUser; import com.orion.ops.framework.common.security.LoginUser;
import com.orion.ops.framework.common.security.UserRole;
import com.orion.ops.framework.common.utils.Valid; import com.orion.ops.framework.common.utils.Valid;
import com.orion.ops.framework.redis.core.utils.RedisStrings; import com.orion.ops.framework.redis.core.utils.RedisStrings;
import com.orion.ops.module.infra.dao.SystemRoleDAO; import com.orion.ops.module.infra.dao.SystemRoleDAO;
@@ -101,25 +102,25 @@ public class SystemUserRoleServiceImpl implements SystemUserRoleService {
effect += addUserRoles.size(); effect += addUserRoles.size();
// 更新缓存中的角色 // 更新缓存中的角色
RedisStrings.<LoginUser>processSetJson(UserCacheKeyDefine.USER_INFO, s -> { RedisStrings.<LoginUser>processSetJson(UserCacheKeyDefine.USER_INFO, s -> {
List<String> roleCodeList = userRoles.stream() List<UserRole> roles = userRoles.stream()
.map(SystemRoleDO::getCode) .map(role -> new UserRole(role.getId(), role.getCode()))
.collect(Collectors.toList()); .collect(Collectors.toList());
s.setRoles(roleCodeList); s.setRoles(roles);
}, userId); }, userId);
return effect; return effect;
} }
@Override @Override
@Async("asyncExecutor") @Async("asyncExecutor")
public void deleteUserCacheRoleAsync(String roleCode, List<Long> userIdList) { public void deleteUserCacheRoleAsync(Long roleId, List<Long> userIdList) {
for (Long userId : userIdList) { for (Long userId : userIdList) {
RedisStrings.<LoginUser>processSetJson(UserCacheKeyDefine.USER_INFO, s -> { RedisStrings.<LoginUser>processSetJson(UserCacheKeyDefine.USER_INFO, s -> {
List<String> roles = s.getRoles(); List<UserRole> roles = s.getRoles();
if (Lists.isEmpty(roles)) { if (Lists.isEmpty(roles)) {
return; return;
} }
// 移除角色 // 移除角色
roles.remove(roleCode); roles.removeIf(role -> roleId.equals(role.getId()));
}, userId); }, userId);
} }
} }

View File

@@ -1,3 +1,4 @@
import type { MenuQueryResponse } from '@/api/system/menu';
import axios from 'axios'; import axios from 'axios';
/** /**
@@ -15,6 +16,22 @@ export interface LoginResponse {
token: string; token: string;
} }
/**
* 用户权限响应
*/
export interface UserPermissionResponse {
user: {
id: number;
username: string;
nickname: string;
avatar: string;
systemPreference: Record<string, any>;
tippedKeys: Array<string>;
};
roles: Array<string>;
permissions: Array<string>;
}
/** /**
* 登录 * 登录
*/ */
@@ -33,12 +50,12 @@ export function logout() {
* 获取用户信息 * 获取用户信息
*/ */
export function getUserPermission() { export function getUserPermission() {
return axios.get('/infra/permission/user'); return axios.get<UserPermissionResponse>('/infra/permission/user');
} }
/** /**
* 获取菜单列表 * 获取菜单列表
*/ */
export function getMenuList() { export function getMenuList() {
return axios.get('/infra/permission/menu'); return axios.get<Array<MenuQueryResponse>>('/infra/permission/menu');
} }

View File

@@ -58,7 +58,7 @@ export default function usePermission() {
* 是否有角色 * 是否有角色
*/ */
hasAnyRole(role: string[]) { hasAnyRole(role: string[]) {
return userStore.roles?.includes('*') || return userStore.roles?.includes('admin') ||
role.map(s => userStore.roles?.includes(s)) role.map(s => userStore.roles?.includes(s))
.filter(Boolean).length > 0; .filter(Boolean).length > 0;
} }

View File

@@ -28,8 +28,8 @@
<!-- 传输框 --> <!-- 传输框 -->
<a-transfer v-model="value" <a-transfer v-model="value"
:data="data" :data="data"
:source-input-search-props="{ placeholder:'请输入主机名称/编码/IP' }" :source-input-search-props="{ placeholder: '请输入主机名称/编码/IP' }"
:target-input-search-props="{ placeholder:'请输入主机名称/编码/IP' }" :target-input-search-props="{ placeholder: '请输入主机名称/编码/IP' }"
:disabled="!group.key" :disabled="!group.key"
show-search show-search
one-way> one-way>

View File

@@ -80,7 +80,7 @@
type="warning" type="warning"
@ok="toggleRoleStatus(record)"> @ok="toggleRoleStatus(record)">
<a-button v-permission="['infra:system-role:delete']" <a-button v-permission="['infra:system-role:delete']"
:disabled="record.code === 'admin'" :disabled="record.code === AdminCode"
:status="toggleDictValue(roleStatusKey, record.status, 'status')" :status="toggleDictValue(roleStatusKey, record.status, 'status')"
type="text" type="text"
size="mini"> size="mini">
@@ -89,7 +89,7 @@
</a-popconfirm> </a-popconfirm>
<!-- 分配菜单 --> <!-- 分配菜单 -->
<a-button v-permission="['infra:system-role:grant-menu']" <a-button v-permission="['infra:system-role:grant-menu']"
:disabled="record.code === 'admin'" :disabled="record.code === AdminCode"
type="text" type="text"
size="mini" size="mini"
@click="emits('openGrant', record)"> @click="emits('openGrant', record)">
@@ -108,7 +108,7 @@
type="warning" type="warning"
@ok="deleteRow(record)"> @ok="deleteRow(record)">
<a-button v-permission="['infra:system-role:delete']" <a-button v-permission="['infra:system-role:delete']"
:disabled="record.code === 'admin'" :disabled="record.code === AdminCode"
type="text" type="text"
size="mini" size="mini"
status="danger"> status="danger">
@@ -134,7 +134,7 @@
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
import useLoading from '@/hooks/loading'; import useLoading from '@/hooks/loading';
import columns from '../types/table.columns'; import columns from '../types/table.columns';
import { roleStatusKey } from '../types/const'; import { roleStatusKey, AdminCode } from '../types/const';
import { usePagination } from '@/types/table'; import { usePagination } from '@/types/table';
import { useDictStore } from '@/store'; import { useDictStore } from '@/store';

View File

@@ -1,3 +1,6 @@
// 管理员角色编码
export const AdminCode = 'admin';
// 角色状态 // 角色状态
export const RoleStatus = { export const RoleStatus = {
// 停用 // 停用