mirror of
https://github.com/yangzongzhuan/RuoYi-Cloud.git
synced 2025-09-04 03:37:06 +00:00
优化权限认证注解
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
package com.ruoyi.common.core.exception.auth;
|
||||
|
||||
/**
|
||||
* 未能通过的登录认证异常
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class NotLoginException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public NotLoginException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package com.ruoyi.common.core.exception.auth;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* 未能通过的权限认证异常
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class NotPermissionException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public NotPermissionException(String permission)
|
||||
{
|
||||
super(permission);
|
||||
}
|
||||
|
||||
public NotPermissionException(String[] permissions)
|
||||
{
|
||||
super(StringUtils.join(permissions, ","));
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package com.ruoyi.common.core.exception.auth;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* 未能通过的角色认证异常
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class NotRoleException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public NotRoleException(String role)
|
||||
{
|
||||
super(role);
|
||||
}
|
||||
|
||||
public NotRoleException(String[] roles)
|
||||
{
|
||||
super(StringUtils.join(roles, ","));
|
||||
}
|
||||
}
|
@@ -42,18 +42,20 @@ public class SecurityUtils
|
||||
*/
|
||||
public static String getToken(HttpServletRequest request)
|
||||
{
|
||||
// 从header获取token标识
|
||||
String token = request.getHeader(SecurityConstants.TOKEN_AUTHENTICATION);
|
||||
return replaceTokenPrefix(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换token前缀
|
||||
* 裁剪token前缀
|
||||
*/
|
||||
public static String replaceTokenPrefix(String token)
|
||||
{
|
||||
// 如果前端设置了令牌前缀,则裁剪掉前缀
|
||||
if (StringUtils.isNotEmpty(token) && token.startsWith(SecurityConstants.TOKEN_PREFIX))
|
||||
{
|
||||
token = token.replace(SecurityConstants.TOKEN_PREFIX, "");
|
||||
token = token.replaceFirst(SecurityConstants.TOKEN_PREFIX, "");
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
@@ -0,0 +1,20 @@
|
||||
package com.ruoyi.common.security.annotation;
|
||||
|
||||
/**
|
||||
* 权限注解的验证模式
|
||||
*
|
||||
* @author ruoyi
|
||||
*
|
||||
*/
|
||||
public enum Logical
|
||||
{
|
||||
/**
|
||||
* 必须具有所有的元素
|
||||
*/
|
||||
AND,
|
||||
|
||||
/**
|
||||
* 只需具有其中一个元素
|
||||
*/
|
||||
OR
|
||||
}
|
@@ -1,46 +0,0 @@
|
||||
package com.ruoyi.common.security.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 权限注解
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface PreAuthorize
|
||||
{
|
||||
/**
|
||||
* 验证用户是否具备某权限
|
||||
*/
|
||||
public String hasPermi() default "";
|
||||
|
||||
/**
|
||||
* 验证用户是否不具备某权限,与 hasPermi逻辑相反
|
||||
*/
|
||||
public String lacksPermi() default "";
|
||||
|
||||
/**
|
||||
* 验证用户是否具有以下任意一个权限
|
||||
*/
|
||||
public String[] hasAnyPermi() default {};
|
||||
|
||||
/**
|
||||
* 判断用户是否拥有某个角色
|
||||
*/
|
||||
public String hasRole() default "";
|
||||
|
||||
/**
|
||||
* 验证用户是否不具备某角色,与 isRole逻辑相反
|
||||
*/
|
||||
public String lacksRole() default "";
|
||||
|
||||
/**
|
||||
* 验证用户是否具有以下任意一个角色
|
||||
*/
|
||||
public String[] hasAnyRoles() default {};
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
package com.ruoyi.common.security.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 登录认证:只有登录之后才能进入该方法
|
||||
*
|
||||
* @author ruoyi
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
public @interface RequiresLogin
|
||||
{
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
package com.ruoyi.common.security.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 权限认证:必须具有指定权限才能进入该方法
|
||||
*
|
||||
* @author ruoyi
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
public @interface RequiresPermissions
|
||||
{
|
||||
/**
|
||||
* 需要校验的权限码
|
||||
*/
|
||||
String[] value() default {};
|
||||
|
||||
/**
|
||||
* 验证模式:AND | OR,默认AND
|
||||
*/
|
||||
Logical logical() default Logical.AND;
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package com.ruoyi.common.security.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 角色认证:必须具有指定角色标识才能进入该方法
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
public @interface RequiresRoles
|
||||
{
|
||||
/**
|
||||
* 需要校验的角色标识
|
||||
*/
|
||||
String[] value() default {};
|
||||
|
||||
/**
|
||||
* 验证逻辑:AND | OR,默认AND
|
||||
*/
|
||||
Logical logical() default Logical.AND;
|
||||
}
|
@@ -1,225 +1,97 @@
|
||||
package com.ruoyi.common.security.aspect;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.Signature;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
import com.ruoyi.common.core.exception.PreAuthorizeException;
|
||||
import com.ruoyi.common.core.utils.StringUtils;
|
||||
import com.ruoyi.common.security.annotation.PreAuthorize;
|
||||
import com.ruoyi.common.security.service.TokenService;
|
||||
import com.ruoyi.system.api.model.LoginUser;
|
||||
|
||||
/**
|
||||
* 自定义权限实现
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class PreAuthorizeAspect
|
||||
{
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
|
||||
/** 所有权限标识 */
|
||||
private static final String ALL_PERMISSION = "*:*:*";
|
||||
|
||||
/** 管理员角色权限标识 */
|
||||
private static final String SUPER_ADMIN = "admin";
|
||||
|
||||
/** 数组为0时 */
|
||||
private static final Integer ARRAY_EMPTY = 0;
|
||||
|
||||
@Around("@annotation(com.ruoyi.common.security.annotation.PreAuthorize)")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable
|
||||
{
|
||||
Signature signature = point.getSignature();
|
||||
MethodSignature methodSignature = (MethodSignature) signature;
|
||||
Method method = methodSignature.getMethod();
|
||||
PreAuthorize annotation = method.getAnnotation(PreAuthorize.class);
|
||||
if (annotation == null)
|
||||
{
|
||||
return point.proceed();
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(annotation.hasPermi()))
|
||||
{
|
||||
if (hasPermi(annotation.hasPermi()))
|
||||
{
|
||||
return point.proceed();
|
||||
}
|
||||
throw new PreAuthorizeException();
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(annotation.lacksPermi()))
|
||||
{
|
||||
if (lacksPermi(annotation.lacksPermi()))
|
||||
{
|
||||
return point.proceed();
|
||||
}
|
||||
throw new PreAuthorizeException();
|
||||
}
|
||||
else if (ARRAY_EMPTY < annotation.hasAnyPermi().length)
|
||||
{
|
||||
if (hasAnyPermi(annotation.hasAnyPermi()))
|
||||
{
|
||||
return point.proceed();
|
||||
}
|
||||
throw new PreAuthorizeException();
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(annotation.hasRole()))
|
||||
{
|
||||
if (hasRole(annotation.hasRole()))
|
||||
{
|
||||
return point.proceed();
|
||||
}
|
||||
throw new PreAuthorizeException();
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(annotation.lacksRole()))
|
||||
{
|
||||
if (lacksRole(annotation.lacksRole()))
|
||||
{
|
||||
return point.proceed();
|
||||
}
|
||||
throw new PreAuthorizeException();
|
||||
}
|
||||
else if (ARRAY_EMPTY < annotation.hasAnyRoles().length)
|
||||
{
|
||||
if (hasAnyRoles(annotation.hasAnyRoles()))
|
||||
{
|
||||
return point.proceed();
|
||||
}
|
||||
throw new PreAuthorizeException();
|
||||
}
|
||||
|
||||
return point.proceed();
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户是否具备某权限
|
||||
*
|
||||
* @param permission 权限字符串
|
||||
* @return 用户是否具备某权限
|
||||
*/
|
||||
public boolean hasPermi(String permission)
|
||||
{
|
||||
LoginUser userInfo = tokenService.getLoginUser();
|
||||
if (StringUtils.isNull(userInfo) || CollectionUtils.isEmpty(userInfo.getPermissions()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return hasPermissions(userInfo.getPermissions(), permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户是否不具备某权限,与 hasPermi逻辑相反
|
||||
*
|
||||
* @param permission 权限字符串
|
||||
* @return 用户是否不具备某权限
|
||||
*/
|
||||
public boolean lacksPermi(String permission)
|
||||
{
|
||||
return hasPermi(permission) != true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户是否具有以下任意一个权限
|
||||
*
|
||||
* @param permissions 权限列表
|
||||
* @return 用户是否具有以下任意一个权限
|
||||
*/
|
||||
public boolean hasAnyPermi(String[] permissions)
|
||||
{
|
||||
LoginUser userInfo = tokenService.getLoginUser();
|
||||
if (StringUtils.isNull(userInfo) || CollectionUtils.isEmpty(userInfo.getPermissions()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Collection<String> authorities = userInfo.getPermissions();
|
||||
for (String permission : permissions)
|
||||
{
|
||||
if (permission != null && hasPermissions(authorities, permission))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断用户是否拥有某个角色
|
||||
*
|
||||
* @param role 角色字符串
|
||||
* @return 用户是否具备某角色
|
||||
*/
|
||||
public boolean hasRole(String role)
|
||||
{
|
||||
LoginUser userInfo = tokenService.getLoginUser();
|
||||
if (StringUtils.isNull(userInfo) || CollectionUtils.isEmpty(userInfo.getRoles()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (String roleKey : userInfo.getRoles())
|
||||
{
|
||||
if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(role))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户是否不具备某角色,与 isRole逻辑相反。
|
||||
*
|
||||
* @param role 角色名称
|
||||
* @return 用户是否不具备某角色
|
||||
*/
|
||||
public boolean lacksRole(String role)
|
||||
{
|
||||
return hasRole(role) != true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户是否具有以下任意一个角色
|
||||
*
|
||||
* @param roles 角色列表
|
||||
* @return 用户是否具有以下任意一个角色
|
||||
*/
|
||||
public boolean hasAnyRoles(String[] roles)
|
||||
{
|
||||
LoginUser userInfo = tokenService.getLoginUser();
|
||||
if (StringUtils.isNull(userInfo) || CollectionUtils.isEmpty(userInfo.getRoles()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (String role : roles)
|
||||
{
|
||||
if (hasRole(role))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否包含权限
|
||||
*
|
||||
* @param authorities 权限列表
|
||||
* @param permission 权限字符串
|
||||
* @return 用户是否具备某权限
|
||||
*/
|
||||
private boolean hasPermissions(Collection<String> authorities, String permission)
|
||||
{
|
||||
return authorities.stream().filter(StringUtils::hasText)
|
||||
.anyMatch(x -> ALL_PERMISSION.contains(x) || PatternMatchUtils.simpleMatch(x, permission));
|
||||
}
|
||||
}
|
||||
package com.ruoyi.common.security.aspect;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.ruoyi.common.security.annotation.RequiresLogin;
|
||||
import com.ruoyi.common.security.annotation.RequiresPermissions;
|
||||
import com.ruoyi.common.security.annotation.RequiresRoles;
|
||||
import com.ruoyi.common.security.auth.AuthUtil;
|
||||
|
||||
/**
|
||||
* 基于 Spring Aop 的注解鉴权
|
||||
*
|
||||
* @author kong
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class PreAuthorizeAspect
|
||||
{
|
||||
/**
|
||||
* 构建
|
||||
*/
|
||||
public PreAuthorizeAspect()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义AOP签名 (切入所有使用鉴权注解的方法)
|
||||
*/
|
||||
public static final String POINTCUT_SIGN = " @annotation(com.ruoyi.common.security.annotation.RequiresLogin) || "
|
||||
+ "@annotation(com.ruoyi.common.security.annotation.RequiresPermissions) || "
|
||||
+ "@annotation(com.ruoyi.common.security.annotation.RequiresRoles)";
|
||||
|
||||
/**
|
||||
* 声明AOP签名
|
||||
*/
|
||||
@Pointcut(POINTCUT_SIGN)
|
||||
public void pointcut()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* 环绕切入
|
||||
*
|
||||
* @param joinPoint 切面对象
|
||||
* @return 底层方法执行后的返回值
|
||||
* @throws Throwable 底层方法抛出的异常
|
||||
*/
|
||||
@Around("pointcut()")
|
||||
public Object around(ProceedingJoinPoint joinPoint) throws Throwable
|
||||
{
|
||||
// 注解鉴权
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
checkMethodAnnotation(signature.getMethod());
|
||||
try
|
||||
{
|
||||
// 执行原有逻辑
|
||||
Object obj = joinPoint.proceed();
|
||||
return obj;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对一个Method对象进行注解检查
|
||||
*/
|
||||
public void checkMethodAnnotation(Method method)
|
||||
{
|
||||
// 校验 @RequiresLogin 注解
|
||||
RequiresLogin requiresLogin = method.getAnnotation(RequiresLogin.class);
|
||||
if (requiresLogin != null)
|
||||
{
|
||||
AuthUtil.checkLogin();
|
||||
}
|
||||
|
||||
// 校验 @RequiresRoles 注解
|
||||
RequiresRoles requiresRoles = method.getAnnotation(RequiresRoles.class);
|
||||
if (requiresRoles != null)
|
||||
{
|
||||
AuthUtil.checkRole(requiresRoles);
|
||||
}
|
||||
|
||||
// 校验 @RequiresPermissions 注解
|
||||
RequiresPermissions requiresPermissions = method.getAnnotation(RequiresPermissions.class);
|
||||
if (requiresPermissions != null)
|
||||
{
|
||||
AuthUtil.checkPermi(requiresPermissions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,329 @@
|
||||
package com.ruoyi.common.security.auth;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
import com.ruoyi.common.core.exception.auth.NotLoginException;
|
||||
import com.ruoyi.common.core.exception.auth.NotPermissionException;
|
||||
import com.ruoyi.common.core.exception.auth.NotRoleException;
|
||||
import com.ruoyi.common.core.utils.SecurityUtils;
|
||||
import com.ruoyi.common.core.utils.SpringUtils;
|
||||
import com.ruoyi.common.core.utils.StringUtils;
|
||||
import com.ruoyi.common.security.annotation.Logical;
|
||||
import com.ruoyi.common.security.annotation.RequiresLogin;
|
||||
import com.ruoyi.common.security.annotation.RequiresPermissions;
|
||||
import com.ruoyi.common.security.annotation.RequiresRoles;
|
||||
import com.ruoyi.common.security.service.TokenService;
|
||||
import com.ruoyi.system.api.model.LoginUser;
|
||||
|
||||
/**
|
||||
* Token 权限验证,逻辑实现类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class AuthLogic
|
||||
{
|
||||
/** 所有权限标识 */
|
||||
private static final String ALL_PERMISSION = "*:*:*";
|
||||
|
||||
/** 管理员角色权限标识 */
|
||||
private static final String SUPER_ADMIN = "admin";
|
||||
|
||||
public TokenService tokenService = SpringUtils.getBean(TokenService.class);
|
||||
|
||||
/**
|
||||
* 检验用户是否已经登录,如未登录,则抛出异常
|
||||
*/
|
||||
public void checkLogin()
|
||||
{
|
||||
getLoginUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户缓存信息, 如果未登录,则抛出异常
|
||||
*
|
||||
* @return 用户缓存信息
|
||||
*/
|
||||
public LoginUser getLoginUser()
|
||||
{
|
||||
String token = SecurityUtils.getToken();
|
||||
if (token == null)
|
||||
{
|
||||
throw new NotLoginException("未提供token");
|
||||
}
|
||||
LoginUser loginUser = tokenService.getLoginUser(token);
|
||||
if (loginUser == null)
|
||||
{
|
||||
throw new NotLoginException("无效的token");
|
||||
}
|
||||
return loginUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户是否具备某权限
|
||||
*
|
||||
* @param permission 权限字符串
|
||||
* @return 用户是否具备某权限
|
||||
*/
|
||||
public boolean hasPermi(String permission)
|
||||
{
|
||||
return hasPermi(getPermiList(), permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户是否具备某权限, 如果验证未通过,则抛出异常: NotPermissionException
|
||||
*
|
||||
* @param permission 权限字符串
|
||||
* @return 用户是否具备某权限
|
||||
*/
|
||||
public void checkPermi(String permission)
|
||||
{
|
||||
if (!hasPermi(getPermiList(), permission))
|
||||
{
|
||||
throw new NotPermissionException(permission);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据注解(@RequiresPermissions)鉴权, 如果验证未通过,则抛出异常: NotPermissionException
|
||||
*
|
||||
* @param requiresPermissions 注解对象
|
||||
*/
|
||||
public void checkPermi(RequiresPermissions requiresPermissions)
|
||||
{
|
||||
if (requiresPermissions.logical() == Logical.AND)
|
||||
{
|
||||
checkPermiAnd(requiresPermissions.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
checkPermiOr(requiresPermissions.value());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户是否含有指定权限,必须全部拥有
|
||||
*
|
||||
* @param permissions 权限列表
|
||||
*/
|
||||
public void checkPermiAnd(String... permissions)
|
||||
{
|
||||
Set<String> permissionList = getPermiList();
|
||||
for (String permission : permissions)
|
||||
{
|
||||
if (!hasPermi(permissionList, permission))
|
||||
{
|
||||
throw new NotPermissionException(permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户是否含有指定权限,只需包含其中一个
|
||||
*
|
||||
* @param permissions 权限码数组
|
||||
*/
|
||||
public void checkPermiOr(String... permissions)
|
||||
{
|
||||
Set<String> permissionList = getPermiList();
|
||||
for (String permission : permissions)
|
||||
{
|
||||
if (hasPermi(permissionList, permission))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (permissions.length > 0)
|
||||
{
|
||||
throw new NotPermissionException(permissions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断用户是否拥有某个角色
|
||||
*
|
||||
* @param role 角色标识
|
||||
* @return 用户是否具备某角色
|
||||
*/
|
||||
public boolean hasRole(String role)
|
||||
{
|
||||
return hasRole(getRoleList(), role);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断用户是否拥有某个角色, 如果验证未通过,则抛出异常: NotRoleException
|
||||
*
|
||||
* @param role 角色标识
|
||||
*/
|
||||
public void checkRole(String role)
|
||||
{
|
||||
if (!hasRole(role))
|
||||
{
|
||||
throw new NotRoleException(role);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据注解(@RequiresRoles)鉴权
|
||||
*
|
||||
* @param requiresRoles 注解对象
|
||||
*/
|
||||
public void checkRole(RequiresRoles requiresRoles)
|
||||
{
|
||||
if (requiresRoles.logical() == Logical.AND)
|
||||
{
|
||||
checkRoleAnd(requiresRoles.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
checkRoleOr(requiresRoles.value());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户是否含有指定角色,必须全部拥有
|
||||
*
|
||||
* @param roles 角色标识数组
|
||||
*/
|
||||
public void checkRoleAnd(String... roles)
|
||||
{
|
||||
Set<String> roleList = getRoleList();
|
||||
for (String role : roles)
|
||||
{
|
||||
if (!hasRole(roleList, role))
|
||||
{
|
||||
throw new NotRoleException(role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户是否含有指定角色,只需包含其中一个
|
||||
*
|
||||
* @param roles 角色标识数组
|
||||
*/
|
||||
public void checkRoleOr(String... roles)
|
||||
{
|
||||
Set<String> roleList = getRoleList();
|
||||
for (String role : roles)
|
||||
{
|
||||
if (hasRole(roleList, role))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (roles.length > 0)
|
||||
{
|
||||
throw new NotRoleException(roles);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据注解(@RequiresLogin)鉴权
|
||||
*
|
||||
* @param at 注解对象
|
||||
*/
|
||||
public void checkByAnnotation(RequiresLogin at)
|
||||
{
|
||||
this.checkLogin();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据注解(@RequiresRoles)鉴权
|
||||
*
|
||||
* @param at 注解对象
|
||||
*/
|
||||
public void checkByAnnotation(RequiresRoles at)
|
||||
{
|
||||
String[] roleArray = at.value();
|
||||
if (at.logical() == Logical.AND)
|
||||
{
|
||||
this.checkRoleAnd(roleArray);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.checkRoleOr(roleArray);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据注解(@RequiresPermissions)鉴权
|
||||
*
|
||||
* @param at 注解对象
|
||||
*/
|
||||
public void checkByAnnotation(RequiresPermissions at)
|
||||
{
|
||||
String[] permissionArray = at.value();
|
||||
if (at.logical() == Logical.AND)
|
||||
{
|
||||
this.checkPermiAnd(permissionArray);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.checkPermiOr(permissionArray);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前账号的角色列表
|
||||
*
|
||||
* @return 角色列表
|
||||
*/
|
||||
public Set<String> getRoleList()
|
||||
{
|
||||
try
|
||||
{
|
||||
LoginUser loginUser = getLoginUser();
|
||||
return loginUser.getRoles();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return new HashSet<>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前账号的权限列表
|
||||
*
|
||||
* @return 权限列表
|
||||
*/
|
||||
public Set<String> getPermiList()
|
||||
{
|
||||
try
|
||||
{
|
||||
LoginUser loginUser = getLoginUser();
|
||||
return loginUser.getPermissions();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return new HashSet<>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否包含权限
|
||||
*
|
||||
* @param authorities 权限列表
|
||||
* @param permission 权限字符串
|
||||
* @return 用户是否具备某权限
|
||||
*/
|
||||
public boolean hasPermi(Collection<String> authorities, String permission)
|
||||
{
|
||||
return authorities.stream().filter(StringUtils::hasText)
|
||||
.anyMatch(x -> ALL_PERMISSION.contains(x) || PatternMatchUtils.simpleMatch(x, permission));
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否包含角色
|
||||
*
|
||||
* @param roles 角色列表
|
||||
* @param role 角色
|
||||
* @return 用户是否具备某角色权限
|
||||
*/
|
||||
public boolean hasRole(Collection<String> roles, String role)
|
||||
{
|
||||
return roles.stream().filter(StringUtils::hasText)
|
||||
.anyMatch(x -> SUPER_ADMIN.contains(x) || PatternMatchUtils.simpleMatch(x, role));
|
||||
}
|
||||
}
|
@@ -0,0 +1,127 @@
|
||||
package com.ruoyi.common.security.auth;
|
||||
|
||||
import com.ruoyi.common.security.annotation.RequiresPermissions;
|
||||
import com.ruoyi.common.security.annotation.RequiresRoles;
|
||||
|
||||
/**
|
||||
* Token 权限验证工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class AuthUtil
|
||||
{
|
||||
/**
|
||||
* 底层的 AuthLogic 对象
|
||||
*/
|
||||
public static AuthLogic authLogic = new AuthLogic();
|
||||
|
||||
/**
|
||||
* 检验当前会话是否已经登录,如未登录,则抛出异常
|
||||
*/
|
||||
public static void checkLogin()
|
||||
{
|
||||
authLogic.checkLogin();
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前账号是否含有指定角色标识, 返回true或false
|
||||
*
|
||||
* @param role 角色标识
|
||||
* @return 是否含有指定角色标识
|
||||
*/
|
||||
public static boolean hasRole(String role)
|
||||
{
|
||||
return authLogic.hasRole(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前账号是否含有指定角色标识, 如果验证未通过,则抛出异常: NotRoleException
|
||||
*
|
||||
* @param role 角色标识
|
||||
*/
|
||||
public static void checkRole(String role)
|
||||
{
|
||||
authLogic.checkRole(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据注解传入参数鉴权, 如果验证未通过,则抛出异常: NotRoleException
|
||||
*
|
||||
* @param requiresRoles 角色权限注解
|
||||
*/
|
||||
public static void checkRole(RequiresRoles requiresRoles)
|
||||
{
|
||||
authLogic.checkRole(requiresRoles);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前账号是否含有指定角色标识 [指定多个,必须全部验证通过]
|
||||
*
|
||||
* @param roles 角色标识数组
|
||||
*/
|
||||
public static void checkRoleAnd(String... roles)
|
||||
{
|
||||
authLogic.checkRoleAnd(roles);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前账号是否含有指定角色标识 [指定多个,只要其一验证通过即可]
|
||||
*
|
||||
* @param roles 角色标识数组
|
||||
*/
|
||||
public static void checkRoleOr(String... roles)
|
||||
{
|
||||
authLogic.checkRoleOr(roles);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前账号是否含有指定权限, 返回true或false
|
||||
*
|
||||
* @param permission 权限码
|
||||
* @return 是否含有指定权限
|
||||
*/
|
||||
public static boolean hasPermi(String permission)
|
||||
{
|
||||
return authLogic.hasPermi(permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前账号是否含有指定权限, 如果验证未通过,则抛出异常: NotPermissionException
|
||||
*
|
||||
* @param permission 权限码
|
||||
*/
|
||||
public static void checkPermi(String permission)
|
||||
{
|
||||
authLogic.checkPermi(permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据注解传入参数鉴权, 如果验证未通过,则抛出异常: NotPermissionException
|
||||
*
|
||||
* @param requiresPermissions 权限注解
|
||||
*/
|
||||
public static void checkPermi(RequiresPermissions requiresPermissions)
|
||||
{
|
||||
authLogic.checkPermi(requiresPermissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前账号是否含有指定权限 [指定多个,必须全部验证通过]
|
||||
*
|
||||
* @param permissions 权限码数组
|
||||
*/
|
||||
public static void checkPermiAnd(String... permissions)
|
||||
{
|
||||
authLogic.checkPermiAnd(permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前账号是否含有指定权限 [指定多个,只要其一验证通过即可]
|
||||
*
|
||||
* @param permissions 权限码数组
|
||||
*/
|
||||
public static void checkPermiOr(String... permissions)
|
||||
{
|
||||
authLogic.checkPermiOr(permissions);
|
||||
}
|
||||
}
|
@@ -11,8 +11,9 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import com.ruoyi.common.core.constant.HttpStatus;
|
||||
import com.ruoyi.common.core.exception.DemoModeException;
|
||||
import com.ruoyi.common.core.exception.InnerAuthException;
|
||||
import com.ruoyi.common.core.exception.PreAuthorizeException;
|
||||
import com.ruoyi.common.core.exception.ServiceException;
|
||||
import com.ruoyi.common.core.exception.auth.NotPermissionException;
|
||||
import com.ruoyi.common.core.exception.auth.NotRoleException;
|
||||
import com.ruoyi.common.core.utils.StringUtils;
|
||||
import com.ruoyi.common.core.web.domain.AjaxResult;
|
||||
|
||||
@@ -27,14 +28,25 @@ public class GlobalExceptionHandler
|
||||
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
|
||||
|
||||
/**
|
||||
* 权限异常
|
||||
* 权限码异常
|
||||
*/
|
||||
@ExceptionHandler(PreAuthorizeException.class)
|
||||
public AjaxResult handlePreAuthorizeException(PreAuthorizeException e, HttpServletRequest request)
|
||||
@ExceptionHandler(NotPermissionException.class)
|
||||
public AjaxResult handleNotPermissionException(NotPermissionException e, HttpServletRequest request)
|
||||
{
|
||||
String requestURI = request.getRequestURI();
|
||||
log.error("请求地址'{}',权限校验失败'{}'", requestURI, e.getMessage());
|
||||
return AjaxResult.error(HttpStatus.FORBIDDEN, "没有权限,请联系管理员授权");
|
||||
log.error("请求地址'{}',权限码校验失败'{}'", requestURI, e.getMessage());
|
||||
return AjaxResult.error(HttpStatus.FORBIDDEN, "没有访问权限,请联系管理员授权");
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色权限异常
|
||||
*/
|
||||
@ExceptionHandler(NotRoleException.class)
|
||||
public AjaxResult handleNotRoleException(NotRoleException e, HttpServletRequest request)
|
||||
{
|
||||
String requestURI = request.getRequestURI();
|
||||
log.error("请求地址'{}',角色权限校验失败'{}'", requestURI, e.getMessage());
|
||||
return AjaxResult.error(HttpStatus.FORBIDDEN, "没有访问权限,请联系管理员授权");
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user