|
|
@@ -2,16 +2,29 @@ package com.platform.service.security;
|
|
|
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
import com.platform.common.model.OauthUser;
|
|
|
+import com.platform.common.model.UserInfo;
|
|
|
import com.platform.common.util.SecurityUtils;
|
|
|
+import com.platform.dao.entity.upms.SysMenu;
|
|
|
+import com.platform.dao.entity.upms.SysRole;
|
|
|
+import com.platform.dao.entity.upms.SysRoleMenu;
|
|
|
+import com.platform.dao.mapper.upms.SysMenuMapper;
|
|
|
+import com.platform.dao.mapper.upms.SysRoleMapper;
|
|
|
+import com.platform.dao.mapper.upms.SysRoleMenuMapper;
|
|
|
+import lombok.AllArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.security.access.AccessDeniedException;
|
|
|
import org.springframework.security.core.Authentication;
|
|
|
import org.springframework.security.core.GrantedAuthority;
|
|
|
import org.springframework.security.core.context.SecurityContextHolder;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
import org.springframework.util.PatternMatchUtils;
|
|
|
import org.springframework.util.StringUtils;
|
|
|
|
|
|
import java.util.Collection;
|
|
|
+import java.util.List;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+import tk.mybatis.mapper.entity.Example;
|
|
|
|
|
|
/**
|
|
|
* @Description 接口权限判断工具
|
|
|
@@ -21,7 +34,14 @@ import java.util.Collection;
|
|
|
*/
|
|
|
@Slf4j
|
|
|
@Component("pms")
|
|
|
+@AllArgsConstructor
|
|
|
public class PermissionService {
|
|
|
+
|
|
|
+ private final SysMenuMapper sysMenuMapper;
|
|
|
+
|
|
|
+ private final SysRoleMenuMapper sysRoleMenuMapper;
|
|
|
+
|
|
|
+ private final SysRoleMapper sysRoleMapper;
|
|
|
/**
|
|
|
* 判断接口是否有xxx:xxx权限
|
|
|
*
|
|
|
@@ -34,13 +54,94 @@ public class PermissionService {
|
|
|
}
|
|
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
|
|
if (authentication == null) {
|
|
|
- return false;
|
|
|
+ throw new AccessDeniedException("用户未认证,无法访问,请先登录");
|
|
|
}
|
|
|
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
|
|
|
- return authorities.stream()
|
|
|
+ boolean has = authorities.stream()
|
|
|
.map(GrantedAuthority::getAuthority)
|
|
|
.filter(StringUtils::hasText)
|
|
|
.anyMatch(x -> PatternMatchUtils.simpleMatch(permission, x));
|
|
|
+ if (!has) {
|
|
|
+ // 提示具体缺少的权限标识、归属角色以及当前用户角色,便于定位权限配置问题
|
|
|
+ throw new AccessDeniedException(buildPermissionDeniedMessage(permission, authentication));
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 拼装无权限提示信息:缺少的权限标识、该权限配置在哪些角色上、当前用户角色
|
|
|
+ *
|
|
|
+ * @param permission 缺少的权限标识
|
|
|
+ * @param authentication 当前登录认证信息
|
|
|
+ * @return 提示信息
|
|
|
+ */
|
|
|
+ private String buildPermissionDeniedMessage(String permission, Authentication authentication) {
|
|
|
+ StringBuilder message = new StringBuilder("缺少权限【").append(permission).append("】");
|
|
|
+ try {
|
|
|
+ // 反查该权限标识配置在哪些角色上,给管理员分配权限提供参考
|
|
|
+ String roleHint = queryRolesByPermission(permission);
|
|
|
+ if (StrUtil.isNotBlank(roleHint)) {
|
|
|
+ message.append(",该权限已配置在角色:").append(roleHint);
|
|
|
+ }
|
|
|
+ // 附带当前用户角色,便于确认该给哪个角色补充权限
|
|
|
+ String userRoleHint = currentUserRoleName(authentication);
|
|
|
+ if (StrUtil.isNotBlank(userRoleHint)) {
|
|
|
+ message.append(",当前用户角色:").append(userRoleHint);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 反查失败不影响主流程,仅提示缺少权限
|
|
|
+ log.warn("反查权限【{}】归属角色失败:{}", permission, e.getMessage());
|
|
|
+ }
|
|
|
+ message.append(",请联系管理员分配该权限");
|
|
|
+ return message.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 反查指定权限标识配置在哪些角色上
|
|
|
+ *
|
|
|
+ * @param permission 权限标识
|
|
|
+ * @return 角色名称列表,逗号分隔;未配置时返回空
|
|
|
+ */
|
|
|
+ private String queryRolesByPermission(String permission) {
|
|
|
+ SysMenu menuQuery = new SysMenu();
|
|
|
+ menuQuery.setPermission(permission);
|
|
|
+ menuQuery.setDelFlag(0);
|
|
|
+ List<SysMenu> menus = sysMenuMapper.select(menuQuery);
|
|
|
+ if (CollectionUtils.isEmpty(menus)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ List<String> menuIds = menus.stream().map(SysMenu::getMenuId).collect(Collectors.toList());
|
|
|
+ Example roleMenuExample = new Example(SysRoleMenu.class);
|
|
|
+ roleMenuExample.createCriteria().andIn("menuId", menuIds);
|
|
|
+ List<SysRoleMenu> roleMenus = sysRoleMenuMapper.selectByExample(roleMenuExample);
|
|
|
+ if (CollectionUtils.isEmpty(roleMenus)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ List<String> roleIds = roleMenus.stream().map(SysRoleMenu::getRoleId).distinct().collect(Collectors.toList());
|
|
|
+ Example roleExample = new Example(SysRole.class);
|
|
|
+ roleExample.createCriteria().andIn("roleId", roleIds);
|
|
|
+ List<SysRole> roles = sysRoleMapper.selectByExample(roleExample);
|
|
|
+ if (CollectionUtils.isEmpty(roles)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return roles.stream().map(SysRole::getRoleName).distinct().collect(Collectors.joining("、"));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前登录用户的角色名称
|
|
|
+ *
|
|
|
+ * @param authentication 当前登录认证信息
|
|
|
+ * @return 角色名称,获取不到时返回空
|
|
|
+ */
|
|
|
+ private String currentUserRoleName(Authentication authentication) {
|
|
|
+ Object principal = authentication.getPrincipal();
|
|
|
+ if (principal instanceof OauthUser) {
|
|
|
+ UserInfo userInfo = ((OauthUser) principal).getUserInfo();
|
|
|
+ if (userInfo != null && StrUtil.isNotBlank(userInfo.getRoleName())) {
|
|
|
+ return userInfo.getRoleName();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -59,11 +160,16 @@ public class PermissionService {
|
|
|
}
|
|
|
try {
|
|
|
String loginClientId = SecurityUtils.getClientId(authentication);
|
|
|
- return clientId.equals(loginClientId);
|
|
|
+ boolean has = clientId.equals(loginClientId);
|
|
|
+ if (!has) {
|
|
|
+ // 提示具体缺少的客户端权限,便于定位权限配置问题
|
|
|
+ throw new AccessDeniedException("当前登录客户端【" + loginClientId + "】缺少权限【" + clientId + "】");
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ } catch (AccessDeniedException e) {
|
|
|
+ throw e;
|
|
|
} catch (Exception e) {
|
|
|
- return false;
|
|
|
+ throw new AccessDeniedException("缺少客户端权限【" + clientId + "】");
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
}
|