mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-10-21 02:57:23 +08:00
@@ -1,5 +1,7 @@
|
|||||||
package cn.dev33.satoken.annotation;
|
package cn.dev33.satoken.annotation;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
@@ -15,4 +17,12 @@ import java.lang.annotation.Target;
|
|||||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||||
public @interface SaCheckLogin {
|
public @interface SaCheckLogin {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多账号体系下使用哪个体系检测登录
|
||||||
|
* 每个StpUtil都有一个stpLogic属性
|
||||||
|
* 初始化StpLogic时, 指定的LoginKey字符串复制到这里
|
||||||
|
* @return LoginKey字符串
|
||||||
|
*/
|
||||||
|
String key() default "login";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -26,5 +26,13 @@ public @interface SaCheckPermission {
|
|||||||
* @return 验证模式
|
* @return 验证模式
|
||||||
*/
|
*/
|
||||||
SaMode mode() default SaMode.AND;
|
SaMode mode() default SaMode.AND;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多账号体系下使用哪个体系检测权限
|
||||||
|
* 每个StpUtil都有一个stpLogic属性
|
||||||
|
* 初始化StpLogic时, 指定的LoginKey字符串复制到这里
|
||||||
|
* @return LoginKey字符串
|
||||||
|
*/
|
||||||
|
String key() default "login";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -26,5 +26,13 @@ public @interface SaCheckRole {
|
|||||||
* @return 验证模式
|
* @return 验证模式
|
||||||
*/
|
*/
|
||||||
SaMode mode() default SaMode.AND;
|
SaMode mode() default SaMode.AND;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多账号体系下使用哪个体系检测角色
|
||||||
|
* 每个StpUtil都有一个stpLogic属性
|
||||||
|
* 初始化StpLogic时, 指定的LoginKey字符串复制到这里
|
||||||
|
* @return LoginKey字符串
|
||||||
|
*/
|
||||||
|
String key() default "login";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,5 @@
|
|||||||
package cn.dev33.satoken.exception;
|
package cn.dev33.satoken.exception;
|
||||||
|
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 没有指定权限码,抛出的异常
|
* 没有指定权限码,抛出的异常
|
||||||
*
|
*
|
||||||
@@ -13,7 +11,7 @@ public class NotPermissionException extends SaTokenException {
|
|||||||
/**
|
/**
|
||||||
* 序列化版本号
|
* 序列化版本号
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = 6806129545290130142L;
|
private static final long serialVersionUID = 6806129545290130141L;
|
||||||
|
|
||||||
/** 权限码 */
|
/** 权限码 */
|
||||||
private String code;
|
private String code;
|
||||||
@@ -39,10 +37,6 @@ public class NotPermissionException extends SaTokenException {
|
|||||||
return loginKey;
|
return loginKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NotPermissionException(String code) {
|
|
||||||
this(code, StpUtil.stpLogic.loginKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
public NotPermissionException(String code, String loginKey) {
|
public NotPermissionException(String code, String loginKey) {
|
||||||
super("无此权限:" + code);
|
super("无此权限:" + code);
|
||||||
this.code = code;
|
this.code = code;
|
||||||
|
@@ -1,7 +1,5 @@
|
|||||||
package cn.dev33.satoken.exception;
|
package cn.dev33.satoken.exception;
|
||||||
|
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 没有指定角色标识,抛出的异常
|
* 没有指定角色标识,抛出的异常
|
||||||
*
|
*
|
||||||
@@ -39,10 +37,6 @@ public class NotRoleException extends SaTokenException {
|
|||||||
return loginKey;
|
return loginKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NotRoleException(String role) {
|
|
||||||
this(role, StpUtil.stpLogic.loginKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
public NotRoleException(String role, String loginKey) {
|
public NotRoleException(String role, String loginKey) {
|
||||||
// 这里到底要不要拼接上loginKey呢?纠结
|
// 这里到底要不要拼接上loginKey呢?纠结
|
||||||
super("无此角色:" + role);
|
super("无此角色:" + role);
|
||||||
|
@@ -1217,65 +1217,32 @@ public class StpLogic {
|
|||||||
|
|
||||||
|
|
||||||
// =================== 其它方法 ===================
|
// =================== 其它方法 ===================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对一个Method对象进行注解检查(注解鉴权内部实现)
|
* 检查当前登录体系是否拥有给定角色
|
||||||
* @param method Method对象
|
* @param roleArray 角色字符串数组
|
||||||
|
* @param saMode SaMode.AND, SaMode.OR
|
||||||
*/
|
*/
|
||||||
public void checkMethodAnnotation(Method method) {
|
public void checkHasRoles(String[] roleArray, SaMode saMode) {
|
||||||
|
if(saMode == SaMode.AND) {
|
||||||
// ----------- 验证登录
|
this.checkRoleAnd(roleArray);
|
||||||
if(method.isAnnotationPresent(SaCheckLogin.class) || method.getDeclaringClass().isAnnotationPresent(SaCheckLogin.class)) {
|
} else {
|
||||||
this.checkLogin();
|
this.checkRoleOr(roleArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------- 验证角色
|
|
||||||
// 验证方法上的
|
|
||||||
SaCheckRole scr = method.getAnnotation(SaCheckRole.class);
|
|
||||||
if(scr != null) {
|
|
||||||
String[] roleArray = scr.value();
|
|
||||||
if(scr.mode() == SaMode.AND) {
|
|
||||||
this.checkRoleAnd(roleArray);
|
|
||||||
} else {
|
|
||||||
this.checkRoleOr(roleArray);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 验证类上的
|
|
||||||
scr = method.getDeclaringClass().getAnnotation(SaCheckRole.class);
|
|
||||||
if(scr != null) {
|
|
||||||
String[] roleArray = scr.value();
|
|
||||||
if(scr.mode() == SaMode.AND) {
|
|
||||||
this.checkRoleAnd(roleArray);
|
|
||||||
} else {
|
|
||||||
this.checkRoleOr(roleArray);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------- 验证权限
|
|
||||||
// 验证方法上的
|
|
||||||
SaCheckPermission scp = method.getAnnotation(SaCheckPermission.class);
|
|
||||||
if(scp != null) {
|
|
||||||
String[] permissionArray = scp.value();
|
|
||||||
if(scp.mode() == SaMode.AND) {
|
|
||||||
this.checkPermissionAnd(permissionArray);
|
|
||||||
} else {
|
|
||||||
this.checkPermissionOr(permissionArray);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 验证类上的
|
|
||||||
scp = method.getDeclaringClass().getAnnotation(SaCheckPermission.class);
|
|
||||||
if(scp != null) {
|
|
||||||
String[] permissionArray = scp.value();
|
|
||||||
if(scp.mode() == SaMode.AND) {
|
|
||||||
this.checkPermissionAnd(permissionArray);
|
|
||||||
} else {
|
|
||||||
this.checkPermissionOr(permissionArray);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证通过
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查当前登录体系是否拥有给定权限
|
||||||
|
* @param permissionArray 权限字符串数组
|
||||||
|
* @param saMode SaMode.AND, SaMode.OR
|
||||||
|
*/
|
||||||
|
public void checkHasPermissions(String[] permissionArray, SaMode saMode) {
|
||||||
|
if(saMode == SaMode.AND) {
|
||||||
|
this.checkPermissionAnd(permissionArray);
|
||||||
|
} else {
|
||||||
|
this.checkPermissionOr(permissionArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// =================== 身份切换 ===================
|
// =================== 身份切换 ===================
|
||||||
|
|
||||||
|
@@ -1,5 +1,10 @@
|
|||||||
package cn.dev33.satoken.aop;
|
package cn.dev33.satoken.aop;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.SaManager;
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||||
|
import cn.dev33.satoken.exception.NotLoginException;
|
||||||
import org.aspectj.lang.ProceedingJoinPoint;
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
import org.aspectj.lang.annotation.Around;
|
import org.aspectj.lang.annotation.Around;
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
@@ -12,6 +17,9 @@ import cn.dev33.satoken.stp.StpLogic;
|
|||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
import cn.dev33.satoken.util.SaTokenConsts;
|
import cn.dev33.satoken.util.SaTokenConsts;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sa-token 基于 Spring Aop 的注解鉴权
|
* sa-token 基于 Spring Aop 的注解鉴权
|
||||||
*
|
*
|
||||||
@@ -58,9 +66,66 @@ public class SaCheckAspect {
|
|||||||
*/
|
*/
|
||||||
@Around("pointcut()")
|
@Around("pointcut()")
|
||||||
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
|
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||||
|
|
||||||
// 注解鉴权
|
// 注解鉴权
|
||||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||||
getStpLogic().checkMethodAnnotation(signature.getMethod());
|
Method method = signature.getMethod();
|
||||||
|
Class<?> cutClass = method.getDeclaringClass();
|
||||||
|
Map<String, StpLogic> stpLogicMap = SaManager.stpLogicMap;
|
||||||
|
|
||||||
|
// ----------- 验证登录
|
||||||
|
SaCheckLogin checkLogin = null;
|
||||||
|
if(method.isAnnotationPresent(SaCheckLogin.class)) { // 方法注解的优先级高于类注解
|
||||||
|
checkLogin = method.getAnnotation(SaCheckLogin.class);
|
||||||
|
} else if(cutClass.isAnnotationPresent(SaCheckLogin.class)) {
|
||||||
|
checkLogin = cutClass.getAnnotation(SaCheckLogin.class);
|
||||||
|
}
|
||||||
|
if (checkLogin != null) {
|
||||||
|
String loginKey = checkLogin.key();
|
||||||
|
if (stpLogicMap.containsKey(loginKey)) {
|
||||||
|
StpLogic stpLogic = stpLogicMap.get(loginKey);
|
||||||
|
stpLogic.checkLogin();
|
||||||
|
} else {
|
||||||
|
// StpUserUtil里面的StpLogic对象只有调用至少一次才会初始化,如果没有初始化SaManager.stpLogicMap里面是没有loginKey的
|
||||||
|
// 还有一种可能是使用者写错了loginKey,这两种方式都会导致SaManager.stpLogicMap查不到loginKey
|
||||||
|
throw NotLoginException.newInstance(loginKey, NotLoginException.DEFAULT_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------- 验证角色
|
||||||
|
SaCheckRole saCheckRole = null;
|
||||||
|
if (method.isAnnotationPresent(SaCheckRole.class)) { // 方法注解的优先级高于类注解
|
||||||
|
saCheckRole = method.getAnnotation(SaCheckRole.class);
|
||||||
|
} else if (cutClass.isAnnotationPresent(SaCheckRole.class)) {
|
||||||
|
saCheckRole = cutClass.getAnnotation(SaCheckRole.class);
|
||||||
|
}
|
||||||
|
if (saCheckRole != null) {
|
||||||
|
String loginKey = saCheckRole.key();
|
||||||
|
if (stpLogicMap.containsKey(loginKey)) {
|
||||||
|
StpLogic stpLogic = stpLogicMap.get(loginKey);
|
||||||
|
stpLogic.checkHasRoles(saCheckRole.value(), saCheckRole.mode());
|
||||||
|
} else {
|
||||||
|
throw NotLoginException.newInstance(loginKey, NotLoginException.DEFAULT_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------- 验证权限
|
||||||
|
SaCheckPermission saCheckPermission = null;
|
||||||
|
if (method.isAnnotationPresent(SaCheckPermission.class)) { // 方法注解的优先级高于类注解
|
||||||
|
saCheckPermission = method.getAnnotation(SaCheckPermission.class);
|
||||||
|
} else if (cutClass.isAnnotationPresent(SaCheckPermission.class)){
|
||||||
|
saCheckPermission = cutClass.getAnnotation(SaCheckPermission.class);
|
||||||
|
}
|
||||||
|
if (saCheckPermission != null) {
|
||||||
|
String loginKey = saCheckPermission.key();
|
||||||
|
if (stpLogicMap.containsKey(loginKey)) {
|
||||||
|
StpLogic stpLogic = stpLogicMap.get(loginKey);
|
||||||
|
stpLogic.checkHasPermissions(saCheckPermission.value(), saCheckPermission.mode());
|
||||||
|
} else {
|
||||||
|
throw NotLoginException.newInstance(loginKey, NotLoginException.DEFAULT_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 执行原有逻辑
|
// 执行原有逻辑
|
||||||
Object obj = joinPoint.proceed();
|
Object obj = joinPoint.proceed();
|
||||||
|
@@ -1,10 +1,16 @@
|
|||||||
package cn.dev33.satoken.interceptor;
|
package cn.dev33.satoken.interceptor;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.SaManager;
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||||
|
import cn.dev33.satoken.exception.NotLoginException;
|
||||||
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.method.HandlerMethod;
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
@@ -62,7 +68,59 @@ public class SaAnnotationInterceptor implements HandlerInterceptor {
|
|||||||
Method method = ((HandlerMethod) handler).getMethod();
|
Method method = ((HandlerMethod) handler).getMethod();
|
||||||
|
|
||||||
// 进行验证
|
// 进行验证
|
||||||
getStpLogic().checkMethodAnnotation(method);
|
Class<?> cutClass = method.getDeclaringClass();
|
||||||
|
Map<String, StpLogic> stpLogicMap = SaManager.stpLogicMap;
|
||||||
|
|
||||||
|
// ----------- 验证登录
|
||||||
|
SaCheckLogin checkLogin = null;
|
||||||
|
if(method.isAnnotationPresent(SaCheckLogin.class)) { // 方法注解的优先级高于类注解
|
||||||
|
checkLogin = method.getAnnotation(SaCheckLogin.class);
|
||||||
|
} else if(cutClass.isAnnotationPresent(SaCheckLogin.class)) {
|
||||||
|
checkLogin = cutClass.getAnnotation(SaCheckLogin.class);
|
||||||
|
}
|
||||||
|
if (checkLogin != null) {
|
||||||
|
String loginKey = checkLogin.key();
|
||||||
|
if (stpLogicMap.containsKey(loginKey)) {
|
||||||
|
StpLogic stpLogic = stpLogicMap.get(loginKey);
|
||||||
|
stpLogic.checkLogin();
|
||||||
|
} else {
|
||||||
|
throw NotLoginException.newInstance(loginKey, NotLoginException.DEFAULT_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------- 验证角色
|
||||||
|
SaCheckRole saCheckRole = null;
|
||||||
|
if (method.isAnnotationPresent(SaCheckRole.class)) { // 方法注解的优先级高于类注解
|
||||||
|
saCheckRole = method.getAnnotation(SaCheckRole.class);
|
||||||
|
} else if (cutClass.isAnnotationPresent(SaCheckRole.class)) {
|
||||||
|
saCheckRole = cutClass.getAnnotation(SaCheckRole.class);
|
||||||
|
}
|
||||||
|
if (saCheckRole != null) {
|
||||||
|
String loginKey = saCheckRole.key();
|
||||||
|
if (stpLogicMap.containsKey(loginKey)) {
|
||||||
|
StpLogic stpLogic = stpLogicMap.get(loginKey);
|
||||||
|
stpLogic.checkHasRoles(saCheckRole.value(), saCheckRole.mode());
|
||||||
|
} else {
|
||||||
|
throw NotLoginException.newInstance(loginKey, NotLoginException.DEFAULT_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------- 验证权限
|
||||||
|
SaCheckPermission saCheckPermission = null;
|
||||||
|
if (method.isAnnotationPresent(SaCheckPermission.class)) { // 方法注解的优先级高于类注解
|
||||||
|
saCheckPermission = method.getAnnotation(SaCheckPermission.class);
|
||||||
|
} else if (cutClass.isAnnotationPresent(SaCheckPermission.class)){
|
||||||
|
saCheckPermission = cutClass.getAnnotation(SaCheckPermission.class);
|
||||||
|
}
|
||||||
|
if (saCheckPermission != null) {
|
||||||
|
String loginKey = saCheckPermission.key();
|
||||||
|
if (stpLogicMap.containsKey(loginKey)) {
|
||||||
|
StpLogic stpLogic = stpLogicMap.get(loginKey);
|
||||||
|
stpLogic.checkHasPermissions(saCheckPermission.value(), saCheckPermission.mode());
|
||||||
|
} else {
|
||||||
|
throw NotLoginException.newInstance(loginKey, NotLoginException.DEFAULT_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 通过验证
|
// 通过验证
|
||||||
return true;
|
return true;
|
||||||
|
Reference in New Issue
Block a user