mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-07-15 14:04:36 +08:00
重构注解鉴权底层,可以方便的自定义注解了
This commit is contained in:
parent
a3746878de
commit
834e1d5b34
@ -39,13 +39,6 @@ public @interface SaCheckOr {
|
|||||||
*/
|
*/
|
||||||
SaCheckLogin[] login() default {};
|
SaCheckLogin[] login() default {};
|
||||||
|
|
||||||
/**
|
|
||||||
* 设定 @SaCheckPermission,参考 {@link SaCheckPermission}
|
|
||||||
*
|
|
||||||
* @return /
|
|
||||||
*/
|
|
||||||
SaCheckPermission[] permission() default {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设定 @SaCheckRole,参考 {@link SaCheckRole}
|
* 设定 @SaCheckRole,参考 {@link SaCheckRole}
|
||||||
*
|
*
|
||||||
@ -53,6 +46,13 @@ public @interface SaCheckOr {
|
|||||||
*/
|
*/
|
||||||
SaCheckRole[] role() default {};
|
SaCheckRole[] role() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设定 @SaCheckPermission,参考 {@link SaCheckPermission}
|
||||||
|
*
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
SaCheckPermission[] permission() default {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设定 @SaCheckSafe,参考 {@link SaCheckSafe}
|
* 设定 @SaCheckSafe,参考 {@link SaCheckSafe}
|
||||||
*
|
*
|
||||||
|
@ -1,99 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2020-2099 sa-token.cc
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package cn.dev33.satoken.basic;
|
|
||||||
|
|
||||||
import cn.dev33.satoken.SaManager;
|
|
||||||
import cn.dev33.satoken.context.SaHolder;
|
|
||||||
import cn.dev33.satoken.error.SaErrorCode;
|
|
||||||
import cn.dev33.satoken.exception.NotBasicAuthException;
|
|
||||||
import cn.dev33.satoken.secure.SaBase64Util;
|
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2> 已更换至包:cn.dev33.satoken.httpauth.basic </h2>
|
|
||||||
* <h2> 已更换名称:SaHttpBasicTemplate </h2>
|
|
||||||
*
|
|
||||||
* Sa-Token Http Basic 认证模块
|
|
||||||
*
|
|
||||||
* @author click33
|
|
||||||
* @since 1.26.0
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class SaBasicTemplate {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 默认的 Realm 领域名称
|
|
||||||
*/
|
|
||||||
public static final String DEFAULT_REALM = "Sa-Token";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 在校验失败时,设置响应头,并抛出异常
|
|
||||||
* @param realm 领域
|
|
||||||
*/
|
|
||||||
public void throwNotBasicAuthException(String realm) {
|
|
||||||
SaHolder.getResponse().setStatus(401).setHeader("WWW-Authenticate", "Basic Realm=" + realm);
|
|
||||||
throw new NotBasicAuthException().setCode(SaErrorCode.CODE_10311);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取浏览器提交的 Basic 参数 (裁剪掉前缀并解码)
|
|
||||||
* @return 值
|
|
||||||
*/
|
|
||||||
public String getAuthorizationValue() {
|
|
||||||
|
|
||||||
// 获取前端提交的请求头 Authorization 参数
|
|
||||||
String authorization = SaHolder.getRequest().getHeader("Authorization");
|
|
||||||
|
|
||||||
// 如果不是以 Basic 作为前缀,则视为无效
|
|
||||||
if(authorization == null || ! authorization.startsWith("Basic ")) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 裁剪前缀并解码
|
|
||||||
return SaBase64Util.decode(authorization.substring(6));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对当前会话进行 Basic 校验(使用全局配置的账号密码),校验不通过则抛出异常
|
|
||||||
*/
|
|
||||||
public void check() {
|
|
||||||
check(DEFAULT_REALM, SaManager.getConfig().getBasic());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对当前会话进行 Basic 校验(手动设置账号密码),校验不通过则抛出异常
|
|
||||||
* @param account 账号(格式为 user:password)
|
|
||||||
*/
|
|
||||||
public void check(String account) {
|
|
||||||
check(DEFAULT_REALM, account);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对当前会话进行 Basic 校验(手动设置 Realm 和 账号密码),校验不通过则抛出异常
|
|
||||||
* @param realm 领域
|
|
||||||
* @param account 账号(格式为 user:password)
|
|
||||||
*/
|
|
||||||
public void check(String realm, String account) {
|
|
||||||
if(SaFoxUtil.isEmpty(account)) {
|
|
||||||
account = SaManager.getConfig().getBasic();
|
|
||||||
}
|
|
||||||
String authorization = getAuthorizationValue();
|
|
||||||
if(SaFoxUtil.isEmpty(authorization) || ! authorization.equals(account)) {
|
|
||||||
throwNotBasicAuthException(realm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2020-2099 sa-token.cc
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package cn.dev33.satoken.basic;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2> 已更换至包:cn.dev33.satoken.httpauth.basic </h2>
|
|
||||||
* <h2> 已更换名称:SaHttpBasicUtil </h2>
|
|
||||||
*
|
|
||||||
* Sa-Token Http Basic 认证模块,Util 工具类
|
|
||||||
*
|
|
||||||
* @author click33
|
|
||||||
* @since 1.26.0
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class SaBasicUtil {
|
|
||||||
|
|
||||||
private SaBasicUtil() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 底层使用的 SaBasicTemplate 对象
|
|
||||||
*/
|
|
||||||
public static SaBasicTemplate saBasicTemplate = new SaBasicTemplate();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取浏览器提交的 Basic 参数 (裁剪掉前缀并解码)
|
|
||||||
* @return 值
|
|
||||||
*/
|
|
||||||
public static String getAuthorizationValue() {
|
|
||||||
return saBasicTemplate.getAuthorizationValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对当前会话进行 Basic 校验(使用全局配置的账号密码),校验不通过则抛出异常
|
|
||||||
*/
|
|
||||||
public static void check() {
|
|
||||||
saBasicTemplate.check();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对当前会话进行 Basic 校验(手动设置账号密码),校验不通过则抛出异常
|
|
||||||
* @param account 账号(格式为 user:password)
|
|
||||||
*/
|
|
||||||
public static void check(String account) {
|
|
||||||
saBasicTemplate.check(account);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对当前会话进行 Basic 校验(手动设置 Realm 和 账号密码),校验不通过则抛出异常
|
|
||||||
* @param realm 领域
|
|
||||||
* @param account 账号(格式为 user:password)
|
|
||||||
*/
|
|
||||||
public static void check(String realm, String account) {
|
|
||||||
saBasicTemplate.check(realm, account);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -21,7 +21,7 @@ package cn.dev33.satoken.exception;
|
|||||||
* @author click33
|
* @author click33
|
||||||
* @since 1.26.0
|
* @since 1.26.0
|
||||||
*/
|
*/
|
||||||
public class NotBasicAuthException extends SaTokenException {
|
public class NotHttpBasicAuthException extends SaTokenException {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 序列化版本号
|
* 序列化版本号
|
||||||
@ -34,7 +34,7 @@ public class NotBasicAuthException extends SaTokenException {
|
|||||||
/**
|
/**
|
||||||
* 一个异常:代表会话未通过 Http Basic 认证
|
* 一个异常:代表会话未通过 Http Basic 认证
|
||||||
*/
|
*/
|
||||||
public NotBasicAuthException() {
|
public NotHttpBasicAuthException() {
|
||||||
super(BE_MESSAGE);
|
super(BE_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
@ -18,7 +18,7 @@ package cn.dev33.satoken.httpauth.basic;
|
|||||||
import cn.dev33.satoken.SaManager;
|
import cn.dev33.satoken.SaManager;
|
||||||
import cn.dev33.satoken.context.SaHolder;
|
import cn.dev33.satoken.context.SaHolder;
|
||||||
import cn.dev33.satoken.error.SaErrorCode;
|
import cn.dev33.satoken.error.SaErrorCode;
|
||||||
import cn.dev33.satoken.exception.NotBasicAuthException;
|
import cn.dev33.satoken.exception.NotHttpBasicAuthException;
|
||||||
import cn.dev33.satoken.secure.SaBase64Util;
|
import cn.dev33.satoken.secure.SaBase64Util;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ public class SaHttpBasicTemplate {
|
|||||||
*/
|
*/
|
||||||
public void throwNotBasicAuthException(String realm) {
|
public void throwNotBasicAuthException(String realm) {
|
||||||
SaHolder.getResponse().setStatus(401).setHeader("WWW-Authenticate", "Basic Realm=" + realm);
|
SaHolder.getResponse().setStatus(401).setHeader("WWW-Authenticate", "Basic Realm=" + realm);
|
||||||
throw new NotBasicAuthException().setCode(SaErrorCode.CODE_10311);
|
throw new NotHttpBasicAuthException().setCode(SaErrorCode.CODE_10311);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -263,11 +263,16 @@ public class SaHttpDigestTemplate {
|
|||||||
check(arr[0], arr[1]);
|
check(arr[0], arr[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------- 过期方法 -----------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据注解 ( @SaCheckHttpDigest ) 鉴权
|
* 根据注解 ( @SaCheckHttpDigest ) 鉴权
|
||||||
*
|
*
|
||||||
* @param at 注解对象
|
* @param at 注解对象
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void checkByAnnotation(SaCheckHttpDigest at) {
|
public void checkByAnnotation(SaCheckHttpDigest at) {
|
||||||
|
|
||||||
// 如果配置了 value,则以 value 优先
|
// 如果配置了 value,则以 value 优先
|
||||||
|
@ -90,11 +90,16 @@ public class SaHttpDigestUtil {
|
|||||||
saHttpDigestTemplate.check();
|
saHttpDigestTemplate.check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------- 过期方法 -----------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据注解 ( @SaCheckHttpDigest ) 鉴权
|
* 根据注解 ( @SaCheckHttpDigest ) 鉴权
|
||||||
*
|
*
|
||||||
* @param at 注解对象
|
* @param at 注解对象
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static void checkByAnnotation(SaCheckHttpDigest at) {
|
public static void checkByAnnotation(SaCheckHttpDigest at) {
|
||||||
saHttpDigestTemplate.checkByAnnotation(at);
|
saHttpDigestTemplate.checkByAnnotation(at);
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ package cn.dev33.satoken.listener;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.handler.SaAnnotationAbstractHandler;
|
||||||
import cn.dev33.satoken.config.SaTokenConfig;
|
import cn.dev33.satoken.config.SaTokenConfig;
|
||||||
import cn.dev33.satoken.error.SaErrorCode;
|
import cn.dev33.satoken.error.SaErrorCode;
|
||||||
import cn.dev33.satoken.exception.SaTokenException;
|
import cn.dev33.satoken.exception.SaTokenException;
|
||||||
@ -287,6 +288,16 @@ public class SaTokenEventCenter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事件发布:有新的注解处理器载入到框架中
|
||||||
|
* @param handler 注解处理器
|
||||||
|
*/
|
||||||
|
public static void doRegisterAnnotationHandler(SaAnnotationAbstractHandler<?> handler) {
|
||||||
|
for (SaTokenListener listener : listenerList) {
|
||||||
|
listener.doRegisterAnnotationHandler(handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 事件发布:有新的 StpLogic 载入到框架中
|
* 事件发布:有新的 StpLogic 载入到框架中
|
||||||
* @param stpLogic /
|
* @param stpLogic /
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package cn.dev33.satoken.listener;
|
package cn.dev33.satoken.listener;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.handler.SaAnnotationAbstractHandler;
|
||||||
import cn.dev33.satoken.config.SaTokenConfig;
|
import cn.dev33.satoken.config.SaTokenConfig;
|
||||||
import cn.dev33.satoken.stp.SaLoginModel;
|
import cn.dev33.satoken.stp.SaLoginModel;
|
||||||
import cn.dev33.satoken.stp.StpLogic;
|
import cn.dev33.satoken.stp.StpLogic;
|
||||||
@ -125,6 +126,12 @@ public interface SaTokenListener {
|
|||||||
*/
|
*/
|
||||||
default void doRegisterComponent(String compName, Object compObj) {}
|
default void doRegisterComponent(String compName, Object compObj) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册了自定义注解处理器
|
||||||
|
* @param handler 注解处理器
|
||||||
|
*/
|
||||||
|
default void doRegisterAnnotationHandler(SaAnnotationAbstractHandler<?> handler) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* StpLogic 对象替换
|
* StpLogic 对象替换
|
||||||
* @param stpLogic /
|
* @param stpLogic /
|
||||||
|
@ -15,13 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package cn.dev33.satoken.listener;
|
package cn.dev33.satoken.listener;
|
||||||
|
|
||||||
import static cn.dev33.satoken.SaManager.log;
|
import cn.dev33.satoken.annotation.handler.SaAnnotationAbstractHandler;
|
||||||
|
|
||||||
import cn.dev33.satoken.config.SaTokenConfig;
|
import cn.dev33.satoken.config.SaTokenConfig;
|
||||||
import cn.dev33.satoken.stp.SaLoginModel;
|
import cn.dev33.satoken.stp.SaLoginModel;
|
||||||
import cn.dev33.satoken.stp.StpLogic;
|
import cn.dev33.satoken.stp.StpLogic;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
|
|
||||||
|
import static cn.dev33.satoken.SaManager.log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sa-Token 侦听器的一个实现:Log 打印
|
* Sa-Token 侦听器的一个实现:Log 打印
|
||||||
*
|
*
|
||||||
@ -130,6 +131,17 @@ public class SaTokenListenerForLog implements SaTokenListener {
|
|||||||
log.info("全局组件 {} 载入成功: {}", compName, canonicalName);
|
log.info("全局组件 {} 载入成功: {}", compName, canonicalName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册了自定义注解处理器
|
||||||
|
* @param handler 注解处理器
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doRegisterAnnotationHandler(SaAnnotationAbstractHandler<?> handler) {
|
||||||
|
if(handler != null) {
|
||||||
|
log.info("注解扩展 @{} (处理器: {})", handler.getHandlerAnnotationClass().getSimpleName(), handler.getClass().getCanonicalName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* StpLogic 对象替换
|
* StpLogic 对象替换
|
||||||
* @param stpLogic /
|
* @param stpLogic /
|
||||||
|
@ -2235,79 +2235,6 @@ public class StpLogic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------- 注解鉴权 -------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据注解 ( @SaCheckLogin ) 鉴权
|
|
||||||
*
|
|
||||||
* @param at 注解对象
|
|
||||||
*/
|
|
||||||
public void checkByAnnotation(SaCheckLogin at) {
|
|
||||||
this.checkLogin();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据注解 ( @SaCheckRole ) 鉴权
|
|
||||||
*
|
|
||||||
* @param at 注解对象
|
|
||||||
*/
|
|
||||||
public void checkByAnnotation(SaCheckRole at) {
|
|
||||||
String[] roleArray = at.value();
|
|
||||||
if(at.mode() == SaMode.AND) {
|
|
||||||
this.checkRoleAnd(roleArray);
|
|
||||||
} else {
|
|
||||||
this.checkRoleOr(roleArray);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据注解 ( @SaCheckPermission ) 鉴权
|
|
||||||
*
|
|
||||||
* @param at 注解对象
|
|
||||||
*/
|
|
||||||
public void checkByAnnotation(SaCheckPermission at) {
|
|
||||||
String[] permissionArray = at.value();
|
|
||||||
try {
|
|
||||||
if(at.mode() == SaMode.AND) {
|
|
||||||
this.checkPermissionAnd(permissionArray);
|
|
||||||
} else {
|
|
||||||
this.checkPermissionOr(permissionArray);
|
|
||||||
}
|
|
||||||
} catch (NotPermissionException e) {
|
|
||||||
// 权限认证校验未通过,再开始角色认证校验
|
|
||||||
for (String role : at.orRole()) {
|
|
||||||
String[] rArr = SaFoxUtil.convertStringToArray(role);
|
|
||||||
// 某一项 role 认证通过,则可以提前退出了,代表通过
|
|
||||||
if (hasRoleAnd(rArr)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据注解 ( @SaCheckSafe ) 鉴权
|
|
||||||
*
|
|
||||||
* @param at 注解对象
|
|
||||||
*/
|
|
||||||
public void checkByAnnotation(SaCheckSafe at) {
|
|
||||||
this.checkSafe(at.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据注解 ( @SaCheckDisable ) 鉴权
|
|
||||||
*
|
|
||||||
* @param at 注解对象
|
|
||||||
*/
|
|
||||||
public void checkByAnnotation(SaCheckDisable at) {
|
|
||||||
Object loginId = getLoginId();
|
|
||||||
for (String service : at.value()) {
|
|
||||||
this.checkDisableLevel(loginId, service, at.level());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------- 账号封禁 -------------------
|
// ------------------- 账号封禁 -------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2937,4 +2864,84 @@ public class StpLogic {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------- 过期方法 -------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据注解 ( @SaCheckLogin ) 鉴权
|
||||||
|
*
|
||||||
|
* @param at 注解对象
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void checkByAnnotation(SaCheckLogin at) {
|
||||||
|
this.checkLogin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据注解 ( @SaCheckRole ) 鉴权
|
||||||
|
*
|
||||||
|
* @param at 注解对象
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void checkByAnnotation(SaCheckRole at) {
|
||||||
|
String[] roleArray = at.value();
|
||||||
|
if(at.mode() == SaMode.AND) {
|
||||||
|
this.checkRoleAnd(roleArray);
|
||||||
|
} else {
|
||||||
|
this.checkRoleOr(roleArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据注解 ( @SaCheckPermission ) 鉴权
|
||||||
|
*
|
||||||
|
* @param at 注解对象
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void checkByAnnotation(SaCheckPermission at) {
|
||||||
|
String[] permissionArray = at.value();
|
||||||
|
try {
|
||||||
|
if(at.mode() == SaMode.AND) {
|
||||||
|
this.checkPermissionAnd(permissionArray);
|
||||||
|
} else {
|
||||||
|
this.checkPermissionOr(permissionArray);
|
||||||
|
}
|
||||||
|
} catch (NotPermissionException e) {
|
||||||
|
// 权限认证校验未通过,再开始角色认证校验
|
||||||
|
for (String role : at.orRole()) {
|
||||||
|
String[] rArr = SaFoxUtil.convertStringToArray(role);
|
||||||
|
// 某一项 role 认证通过,则可以提前退出了,代表通过
|
||||||
|
if (hasRoleAnd(rArr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据注解 ( @SaCheckSafe ) 鉴权
|
||||||
|
*
|
||||||
|
* @param at 注解对象
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void checkByAnnotation(SaCheckSafe at) {
|
||||||
|
this.checkSafe(at.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据注解 ( @SaCheckDisable ) 鉴权
|
||||||
|
*
|
||||||
|
* @param at 注解对象
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void checkByAnnotation(SaCheckDisable at) {
|
||||||
|
Object loginId = getLoginId();
|
||||||
|
for (String service : at.value()) {
|
||||||
|
this.checkDisableLevel(loginId, service, at.level());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,19 +16,14 @@
|
|||||||
package cn.dev33.satoken.strategy;
|
package cn.dev33.satoken.strategy;
|
||||||
|
|
||||||
import cn.dev33.satoken.SaManager;
|
import cn.dev33.satoken.SaManager;
|
||||||
import cn.dev33.satoken.annotation.*;
|
|
||||||
import cn.dev33.satoken.exception.RequestPathInvalidException;
|
import cn.dev33.satoken.exception.RequestPathInvalidException;
|
||||||
import cn.dev33.satoken.exception.SaTokenException;
|
import cn.dev33.satoken.exception.SaTokenException;
|
||||||
import cn.dev33.satoken.fun.strategy.*;
|
import cn.dev33.satoken.fun.strategy.*;
|
||||||
import cn.dev33.satoken.httpauth.basic.SaHttpBasicUtil;
|
|
||||||
import cn.dev33.satoken.httpauth.digest.SaHttpDigestUtil;
|
|
||||||
import cn.dev33.satoken.session.SaSession;
|
import cn.dev33.satoken.session.SaSession;
|
||||||
import cn.dev33.satoken.stp.StpLogic;
|
import cn.dev33.satoken.stp.StpLogic;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
import cn.dev33.satoken.util.SaTokenConsts;
|
import cn.dev33.satoken.util.SaTokenConsts;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,185 +128,6 @@ public final class SaStrategy {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 对一个 [Method] 对象进行注解校验 (注解鉴权内部实现)
|
|
||||||
*/
|
|
||||||
public SaCheckMethodAnnotationFunction checkMethodAnnotation = (method) -> {
|
|
||||||
|
|
||||||
// 先校验 Method 所属 Class 上的注解
|
|
||||||
instance.checkElementAnnotation.accept(method.getDeclaringClass());
|
|
||||||
|
|
||||||
// 再校验 Method 上的注解
|
|
||||||
instance.checkElementAnnotation.accept(method);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对一个 [元素] 对象进行注解校验 (注解鉴权内部实现)
|
|
||||||
*/
|
|
||||||
public SaCheckElementAnnotationFunction checkElementAnnotation = (element) -> {
|
|
||||||
|
|
||||||
// 校验 @SaCheckLogin 注解
|
|
||||||
SaCheckLogin checkLogin = (SaCheckLogin) SaStrategy.instance.getAnnotation.apply(element, SaCheckLogin.class);
|
|
||||||
if(checkLogin != null) {
|
|
||||||
SaManager.getStpLogic(checkLogin.type(), false).checkByAnnotation(checkLogin);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 校验 @SaCheckRole 注解
|
|
||||||
SaCheckRole checkRole = (SaCheckRole) SaStrategy.instance.getAnnotation.apply(element, SaCheckRole.class);
|
|
||||||
if(checkRole != null) {
|
|
||||||
SaManager.getStpLogic(checkRole.type(), false).checkByAnnotation(checkRole);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 校验 @SaCheckPermission 注解
|
|
||||||
SaCheckPermission checkPermission = (SaCheckPermission) SaStrategy.instance.getAnnotation.apply(element, SaCheckPermission.class);
|
|
||||||
if(checkPermission != null) {
|
|
||||||
SaManager.getStpLogic(checkPermission.type(), false).checkByAnnotation(checkPermission);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 校验 @SaCheckSafe 注解
|
|
||||||
SaCheckSafe checkSafe = (SaCheckSafe) SaStrategy.instance.getAnnotation.apply(element, SaCheckSafe.class);
|
|
||||||
if(checkSafe != null) {
|
|
||||||
SaManager.getStpLogic(checkSafe.type(), false).checkByAnnotation(checkSafe);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 校验 @SaCheckDisable 注解
|
|
||||||
SaCheckDisable checkDisable = (SaCheckDisable) SaStrategy.instance.getAnnotation.apply(element, SaCheckDisable.class);
|
|
||||||
if(checkDisable != null) {
|
|
||||||
SaManager.getStpLogic(checkDisable.type(), false).checkByAnnotation(checkDisable);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 校验 @SaCheckHttpBasic 注解
|
|
||||||
SaCheckHttpBasic checkHttpBasic = (SaCheckHttpBasic) SaStrategy.instance.getAnnotation.apply(element, SaCheckHttpBasic.class);
|
|
||||||
if(checkHttpBasic != null) {
|
|
||||||
SaHttpBasicUtil.check(checkHttpBasic.realm(), checkHttpBasic.account());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 校验 @SaCheckHttpDigest 注解
|
|
||||||
SaCheckHttpDigest checkHttpDigest = (SaCheckHttpDigest) SaStrategy.instance.getAnnotation.apply(element, SaCheckHttpDigest.class);
|
|
||||||
if(checkHttpDigest != null) {
|
|
||||||
SaHttpDigestUtil.checkByAnnotation(checkHttpDigest);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 校验 @SaCheckOr 注解
|
|
||||||
SaCheckOr checkOr = (SaCheckOr) SaStrategy.instance.getAnnotation.apply(element, SaCheckOr.class);
|
|
||||||
if(checkOr != null) {
|
|
||||||
SaStrategy.instance.checkOrAnnotation.accept(checkOr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对一个 @SaCheckOr 进行注解校验
|
|
||||||
*/
|
|
||||||
public SaCheckOrAnnotationFunction checkOrAnnotation = (at) -> {
|
|
||||||
|
|
||||||
// 记录校验过程中所有的异常
|
|
||||||
List<SaTokenException> errorList = new ArrayList<>();
|
|
||||||
|
|
||||||
// 逐个开始校验 >>>
|
|
||||||
|
|
||||||
// 1、校验注解:@SaCheckLogin
|
|
||||||
SaCheckLogin[] checkLoginArray = at.login();
|
|
||||||
for (SaCheckLogin item : checkLoginArray) {
|
|
||||||
try {
|
|
||||||
SaManager.getStpLogic(item.type(), false).checkByAnnotation(item);
|
|
||||||
return;
|
|
||||||
} catch (SaTokenException e) {
|
|
||||||
errorList.add(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2、校验注解:@SaCheckRole
|
|
||||||
SaCheckRole[] checkRoleArray = at.role();
|
|
||||||
for (SaCheckRole item : checkRoleArray) {
|
|
||||||
try {
|
|
||||||
SaManager.getStpLogic(item.type(), false).checkByAnnotation(item);
|
|
||||||
return;
|
|
||||||
} catch (SaTokenException e) {
|
|
||||||
errorList.add(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3、校验注解:@SaCheckPermission
|
|
||||||
SaCheckPermission[] checkPermissionArray = at.permission();
|
|
||||||
for (SaCheckPermission item : checkPermissionArray) {
|
|
||||||
try {
|
|
||||||
SaManager.getStpLogic(item.type(), false).checkByAnnotation(item);
|
|
||||||
return;
|
|
||||||
} catch (SaTokenException e) {
|
|
||||||
errorList.add(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4、校验注解:@SaCheckSafe
|
|
||||||
SaCheckSafe[] checkSafeArray = at.safe();
|
|
||||||
for (SaCheckSafe item : checkSafeArray) {
|
|
||||||
try {
|
|
||||||
SaManager.getStpLogic(item.type(), false).checkByAnnotation(item);
|
|
||||||
return;
|
|
||||||
} catch (SaTokenException e) {
|
|
||||||
errorList.add(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5、校验注解:@SaCheckDisable
|
|
||||||
SaCheckDisable[] checkDisableArray = at.disable();
|
|
||||||
for (SaCheckDisable item : checkDisableArray) {
|
|
||||||
try {
|
|
||||||
SaManager.getStpLogic(item.type(), false).checkByAnnotation(item);
|
|
||||||
return;
|
|
||||||
} catch (SaTokenException e) {
|
|
||||||
errorList.add(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6、校验注解:@SaCheckBasic
|
|
||||||
SaCheckHttpBasic[] checkHttpBasicArray = at.httpBasic();
|
|
||||||
for (SaCheckHttpBasic item : checkHttpBasicArray) {
|
|
||||||
try {
|
|
||||||
SaHttpBasicUtil.check(item.realm(), item.account());
|
|
||||||
return;
|
|
||||||
} catch (SaTokenException e) {
|
|
||||||
errorList.add(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 7、校验注解:@SaCheckDigest
|
|
||||||
SaCheckHttpDigest[] checkHttpDigestArray = at.httpDigest();
|
|
||||||
for (SaCheckHttpDigest item : checkHttpDigestArray) {
|
|
||||||
try {
|
|
||||||
SaHttpDigestUtil.checkByAnnotation(item);
|
|
||||||
return;
|
|
||||||
} catch (SaTokenException e) {
|
|
||||||
errorList.add(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果执行到这里,有两种可能:
|
|
||||||
// 可能 1. SaCheckOr 注解上不包含任何注解校验,此时 errorList 里面一个异常都没有,我们直接跳过即可
|
|
||||||
// 可能 2. 所有注解校验都通过不了,此时 errorList 里面会有多个异常,我们随便抛出一个即可
|
|
||||||
if(errorList.size() == 0) {
|
|
||||||
// return;
|
|
||||||
} else {
|
|
||||||
throw errorList.get(0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 从元素上获取注解
|
|
||||||
*/
|
|
||||||
public SaGetAnnotationFunction getAnnotation = (element, annotationClass)->{
|
|
||||||
// 默认使用jdk的注解处理器
|
|
||||||
return element.getAnnotation(annotationClass);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断一个 Method 或其所属 Class 是否包含指定注解
|
|
||||||
*/
|
|
||||||
public SaIsAnnotationPresentFunction isAnnotationPresent = (method, annotationClass) -> {
|
|
||||||
return instance.getAnnotation.apply(method, annotationClass) != null ||
|
|
||||||
instance.getAnnotation.apply(method.getDeclaringClass(), annotationClass) != null;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成唯一式 token 的算法
|
* 生成唯一式 token 的算法
|
||||||
*/
|
*/
|
||||||
@ -427,62 +243,6 @@ public final class SaStrategy {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 对一个 [Method] 对象进行注解校验 (注解鉴权内部实现)
|
|
||||||
*
|
|
||||||
* @param checkMethodAnnotation /
|
|
||||||
* @return /
|
|
||||||
*/
|
|
||||||
public SaStrategy setCheckMethodAnnotation(SaCheckMethodAnnotationFunction checkMethodAnnotation) {
|
|
||||||
this.checkMethodAnnotation = checkMethodAnnotation;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对一个 [元素] 对象进行注解校验 (注解鉴权内部实现)
|
|
||||||
*
|
|
||||||
* @param checkElementAnnotation /
|
|
||||||
* @return /
|
|
||||||
*/
|
|
||||||
public SaStrategy setCheckElementAnnotation(SaCheckElementAnnotationFunction checkElementAnnotation) {
|
|
||||||
this.checkElementAnnotation = checkElementAnnotation;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对一个 @SaCheckOr 进行注解校验
|
|
||||||
* <p> 参数 [SaCheckOr 注解的实例]
|
|
||||||
*
|
|
||||||
* @param checkOrAnnotation /
|
|
||||||
* @return /
|
|
||||||
*/
|
|
||||||
public SaStrategy setCheckOrAnnotation(SaCheckOrAnnotationFunction checkOrAnnotation) {
|
|
||||||
this.checkOrAnnotation = checkOrAnnotation;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 从元素上获取注解
|
|
||||||
*
|
|
||||||
* @param getAnnotation /
|
|
||||||
* @return /
|
|
||||||
*/
|
|
||||||
public SaStrategy setGetAnnotation(SaGetAnnotationFunction getAnnotation) {
|
|
||||||
this.getAnnotation = getAnnotation;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断一个 Method 或其所属 Class 是否包含指定注解
|
|
||||||
*
|
|
||||||
* @param isAnnotationPresent /
|
|
||||||
* @return /
|
|
||||||
*/
|
|
||||||
public SaStrategy setIsAnnotationPresent(SaIsAnnotationPresentFunction isAnnotationPresent) {
|
|
||||||
this.isAnnotationPresent = isAnnotationPresent;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成唯一式 token 的算法
|
* 生成唯一式 token 的算法
|
||||||
*
|
*
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
package com.pj;
|
package com.pj;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.SaManager;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
import cn.dev33.satoken.SaManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sa-Token 示例
|
* Sa-Token 示例
|
||||||
* @author click33
|
* @author click33
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
package com.pj.cases.test;
|
package com.pj.cases.test;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.util.SaResult;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import cn.dev33.satoken.util.SaResult;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 测试专用 Controller
|
* 测试专用 Controller
|
||||||
* @author click33
|
* @author click33
|
||||||
|
@ -4,7 +4,7 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
|
|||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
import cn.dev33.satoken.exception.DisableServiceException;
|
import cn.dev33.satoken.exception.DisableServiceException;
|
||||||
import cn.dev33.satoken.exception.NotBasicAuthException;
|
import cn.dev33.satoken.exception.NotHttpBasicAuthException;
|
||||||
import cn.dev33.satoken.exception.NotLoginException;
|
import cn.dev33.satoken.exception.NotLoginException;
|
||||||
import cn.dev33.satoken.exception.NotPermissionException;
|
import cn.dev33.satoken.exception.NotPermissionException;
|
||||||
import cn.dev33.satoken.exception.NotRoleException;
|
import cn.dev33.satoken.exception.NotRoleException;
|
||||||
@ -57,8 +57,8 @@ public class GlobalException {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 拦截:Http Basic 校验失败异常
|
// 拦截:Http Basic 校验失败异常
|
||||||
@ExceptionHandler(NotBasicAuthException.class)
|
@ExceptionHandler(NotHttpBasicAuthException.class)
|
||||||
public SaResult handlerException(NotBasicAuthException e) {
|
public SaResult handlerException(NotHttpBasicAuthException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return SaResult.error(e.getMessage());
|
return SaResult.error(e.getMessage());
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import cn.dev33.satoken.filter.SaServletFilter;
|
|||||||
import cn.dev33.satoken.interceptor.SaInterceptor;
|
import cn.dev33.satoken.interceptor.SaInterceptor;
|
||||||
import cn.dev33.satoken.router.SaRouter;
|
import cn.dev33.satoken.router.SaRouter;
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.dev33.satoken.strategy.SaAnnotationStrategy;
|
||||||
import cn.dev33.satoken.strategy.SaStrategy;
|
import cn.dev33.satoken.strategy.SaStrategy;
|
||||||
import cn.dev33.satoken.util.SaResult;
|
import cn.dev33.satoken.util.SaResult;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@ -117,9 +118,9 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
|||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void rewriteSaStrategy() {
|
public void rewriteSaStrategy() {
|
||||||
// 重写Sa-Token的注解处理器,增加注解合并功能
|
// 重写Sa-Token的注解处理器,增加注解合并功能
|
||||||
SaStrategy.instance.getAnnotation = (element, annotationClass) -> {
|
// SaAnnotationStrategy.instance.getAnnotation = (element, annotationClass) -> {
|
||||||
return AnnotatedElementUtils.getMergedAnnotation(element, annotationClass);
|
// return AnnotatedElementUtils.getMergedAnnotation(element, annotationClass);
|
||||||
};
|
// };
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,16 @@
|
|||||||
package com.pj.satoken.at;
|
package com.pj.satoken.custom_annotation;
|
||||||
|
|
||||||
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;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
|
||||||
import com.pj.satoken.StpUserUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录认证(User版):只有登录之后才能进入该方法
|
* 登录认证(User版):只有登录之后才能进入该方法
|
||||||
* <p> 可标注在函数、类上(效果等同于标注在此类的所有方法上)
|
* <p> 可标注在函数、类上(效果等同于标注在此类的所有方法上)
|
||||||
* @author click33
|
|
||||||
*
|
*
|
||||||
|
* @author click33
|
||||||
*/
|
*/
|
||||||
@SaCheckLogin(type = StpUserUtil.TYPE)
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ ElementType.METHOD, ElementType.TYPE})
|
@Target({ ElementType.METHOD, ElementType.TYPE})
|
||||||
public @interface SaUserCheckLogin {
|
public @interface SaUserCheckLogin {
|
@ -1,23 +1,19 @@
|
|||||||
package com.pj.satoken.at;
|
package com.pj.satoken.custom_annotation;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaMode;
|
||||||
|
|
||||||
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;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
import com.pj.satoken.StpUserUtil;
|
|
||||||
import org.springframework.core.annotation.AliasFor;
|
|
||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
|
||||||
import cn.dev33.satoken.annotation.SaMode;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 权限认证(User版):必须具有指定权限才能进入该方法
|
* 权限认证(User版):必须具有指定权限才能进入该方法
|
||||||
* <p> 可标注在函数、类上(效果等同于标注在此类的所有方法上)
|
* <p> 可标注在函数、类上(效果等同于标注在此类的所有方法上)
|
||||||
|
*
|
||||||
* @author click33
|
* @author click33
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@SaCheckPermission(type = StpUserUtil.TYPE)
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ ElementType.METHOD, ElementType.TYPE})
|
@Target({ ElementType.METHOD, ElementType.TYPE})
|
||||||
public @interface SaUserCheckPermission {
|
public @interface SaUserCheckPermission {
|
||||||
@ -26,14 +22,29 @@ public @interface SaUserCheckPermission {
|
|||||||
* 需要校验的权限码
|
* 需要校验的权限码
|
||||||
* @return 需要校验的权限码
|
* @return 需要校验的权限码
|
||||||
*/
|
*/
|
||||||
@AliasFor(annotation = SaCheckPermission.class)
|
|
||||||
String [] value() default {};
|
String [] value() default {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证模式:AND | OR,默认AND
|
* 验证模式:AND | OR,默认AND
|
||||||
* @return 验证模式
|
* @return 验证模式
|
||||||
*/
|
*/
|
||||||
@AliasFor(annotation = SaCheckPermission.class)
|
|
||||||
SaMode mode() default SaMode.AND;
|
SaMode mode() default SaMode.AND;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在权限校验不通过时的次要选择,两者只要其一校验成功即可通过校验
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 例1:@SaCheckPermission(value="user-add", orRole="admin"),
|
||||||
|
* 代表本次请求只要具有 user-add权限 或 admin角色 其一即可通过校验。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 例2: orRole = {"admin", "manager", "staff"},具有三个角色其一即可。 <br>
|
||||||
|
* 例3: orRole = {"admin, manager, staff"},必须三个角色同时具备。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
String[] orRole() default {};
|
||||||
|
|
||||||
}
|
}
|
@ -1,23 +1,18 @@
|
|||||||
package com.pj.satoken.at;
|
package com.pj.satoken.custom_annotation;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaMode;
|
||||||
|
|
||||||
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;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
import com.pj.satoken.StpUserUtil;
|
|
||||||
import org.springframework.core.annotation.AliasFor;
|
|
||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaCheckRole;
|
|
||||||
import cn.dev33.satoken.annotation.SaMode;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 角色认证(User版):必须具有指定角色标识才能进入该方法
|
* 角色认证(User版):必须具有指定角色标识才能进入该方法
|
||||||
* <p> 可标注在函数、类上(效果等同于标注在此类的所有方法上)
|
* <p> 可标注在函数、类上(效果等同于标注在此类的所有方法上)
|
||||||
* @author click33
|
* @author click33
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@SaCheckRole(type = StpUserUtil.TYPE)
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ ElementType.METHOD, ElementType.TYPE})
|
@Target({ ElementType.METHOD, ElementType.TYPE})
|
||||||
public @interface SaUserCheckRole {
|
public @interface SaUserCheckRole {
|
||||||
@ -26,14 +21,12 @@ public @interface SaUserCheckRole {
|
|||||||
* 需要校验的角色标识
|
* 需要校验的角色标识
|
||||||
* @return 需要校验的角色标识
|
* @return 需要校验的角色标识
|
||||||
*/
|
*/
|
||||||
@AliasFor(annotation = SaCheckRole.class)
|
|
||||||
String [] value() default {};
|
String [] value() default {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证模式:AND | OR,默认AND
|
* 验证模式:AND | OR,默认AND
|
||||||
* @return 验证模式
|
* @return 验证模式
|
||||||
*/
|
*/
|
||||||
@AliasFor(annotation = SaCheckRole.class)
|
|
||||||
SaMode mode() default SaMode.AND;
|
SaMode mode() default SaMode.AND;
|
||||||
|
|
||||||
}
|
}
|
@ -108,6 +108,7 @@
|
|||||||
- [TokenInfo参数详解](/fun/token-info)
|
- [TokenInfo参数详解](/fun/token-info)
|
||||||
- [异常细分状态码](/fun/exception-code)
|
- [异常细分状态码](/fun/exception-code)
|
||||||
- [数据结构](/fun/data-structure)
|
- [数据结构](/fun/data-structure)
|
||||||
|
- [自定义注解](/fun/custom-annotations)
|
||||||
- [参考:把权限放在缓存里](/fun/jur-cache)
|
- [参考:把权限放在缓存里](/fun/jur-cache)
|
||||||
- [参考:把路由拦截鉴权动态化](/fun/dynamic-router-check)
|
- [参考:把路由拦截鉴权动态化](/fun/dynamic-router-check)
|
||||||
- [解决反向代理 uri 丢失的问题](/fun/curr-domain)
|
- [解决反向代理 uri 丢失的问题](/fun/curr-domain)
|
||||||
|
@ -184,8 +184,11 @@ public String info() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
注:其它注解 `@SaCheckRole("xxx")`、`@SaCheckPermission("xxx")`同理,
|
注:其它注解 `@SaCheckRole("xxx")`、`@SaCheckPermission("xxx")`同理, 完整示例参考 Gitee 代码:
|
||||||
完整示例参考:[码云:自定义注解](https://gitee.com/dromara/sa-token/tree/dev/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/at)。
|
[注解合并](https://gitee.com/dromara/sa-token/tree/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/merge_annotation)。
|
||||||
|
|
||||||
|
> [!TIP| label:自定义注解方案]
|
||||||
|
> 除了注解合并方案,这里还有一份自定义注解方案,参考:[自定义注解](/fun/custom-annotations)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -213,10 +213,16 @@ public SaResult test() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 7、在业务逻辑层使用注解鉴权
|
### 7、扩展阅读
|
||||||
疑问:我能否将注解写在其它架构层呢,比如业务逻辑层?
|
|
||||||
|
|
||||||
使用拦截器模式,只能在`Controller层`进行注解鉴权,如需在任意层级使用注解鉴权,请参考:[AOP注解鉴权](/plugin/aop-at)
|
- 在业务逻辑层使用鉴权注解:[AOP注解鉴权](/plugin/aop-at)
|
||||||
|
|
||||||
|
- 制作自定义鉴权注解注入到框架:[自定义注解](/fun/custom-annotations)
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 疑问:我能否将注解写在其它架构层呢,比如业务逻辑层?
|
||||||
|
|
||||||
|
使用拦截器模式,只能在`Controller层`进行注解鉴权,如需在任意层级使用注解鉴权,请参考:[AOP注解鉴权](/plugin/aop-at) -->
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package cn.dev33.satoken.spring;
|
package cn.dev33.satoken.spring;
|
||||||
|
|
||||||
import cn.dev33.satoken.SaManager;
|
import cn.dev33.satoken.SaManager;
|
||||||
|
import cn.dev33.satoken.annotation.handler.SaAnnotationAbstractHandler;
|
||||||
import cn.dev33.satoken.config.SaTokenConfig;
|
import cn.dev33.satoken.config.SaTokenConfig;
|
||||||
import cn.dev33.satoken.context.SaTokenContext;
|
import cn.dev33.satoken.context.SaTokenContext;
|
||||||
import cn.dev33.satoken.context.second.SaTokenSecondContextCreator;
|
import cn.dev33.satoken.context.second.SaTokenSecondContextCreator;
|
||||||
@ -34,6 +35,7 @@ import cn.dev33.satoken.spring.pathmatch.SaPathMatcherHolder;
|
|||||||
import cn.dev33.satoken.stp.StpInterface;
|
import cn.dev33.satoken.stp.StpInterface;
|
||||||
import cn.dev33.satoken.stp.StpLogic;
|
import cn.dev33.satoken.stp.StpLogic;
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.dev33.satoken.strategy.SaAnnotationStrategy;
|
||||||
import cn.dev33.satoken.temp.SaTempInterface;
|
import cn.dev33.satoken.temp.SaTempInterface;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
@ -118,6 +120,18 @@ public class SaBeanInject {
|
|||||||
SaTokenEventCenter.registerListenerList(listenerList);
|
SaTokenEventCenter.registerListenerList(listenerList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注入自定义注解处理器
|
||||||
|
*
|
||||||
|
* @param handlerList 自定义注解处理器集合
|
||||||
|
*/
|
||||||
|
@Autowired(required = false)
|
||||||
|
public void setSaAnnotationHandler(List<SaAnnotationAbstractHandler<?>> handlerList) {
|
||||||
|
for (SaAnnotationAbstractHandler<?> handler : handlerList) {
|
||||||
|
SaAnnotationStrategy.instance.registerAnnotationHandler(handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注入临时令牌验证模块 Bean
|
* 注入临时令牌验证模块 Bean
|
||||||
*
|
*
|
||||||
@ -149,12 +163,12 @@ public class SaBeanInject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注入 Sa-Token Digest Basic 认证模块
|
* 注入 Sa-Token Http Digest 认证模块
|
||||||
*
|
*
|
||||||
* @param saHttpDigestTemplate saHttpDigestTemplate 对象
|
* @param saHttpDigestTemplate saHttpDigestTemplate 对象
|
||||||
*/
|
*/
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
public void setSaHttpBasicTemplate(SaHttpDigestTemplate saHttpDigestTemplate) {
|
public void setSaHttpDigestTemplate(SaHttpDigestTemplate saHttpDigestTemplate) {
|
||||||
SaHttpDigestUtil.saHttpDigestTemplate = saHttpDigestTemplate;
|
SaHttpDigestUtil.saHttpDigestTemplate = saHttpDigestTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,11 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package cn.dev33.satoken.interceptor;
|
package cn.dev33.satoken.interceptor;
|
||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaIgnore;
|
|
||||||
import cn.dev33.satoken.exception.BackResultException;
|
import cn.dev33.satoken.exception.BackResultException;
|
||||||
import cn.dev33.satoken.exception.StopMatchException;
|
import cn.dev33.satoken.exception.StopMatchException;
|
||||||
import cn.dev33.satoken.fun.SaParamFunction;
|
import cn.dev33.satoken.fun.SaParamFunction;
|
||||||
import cn.dev33.satoken.strategy.SaStrategy;
|
import cn.dev33.satoken.strategy.SaAnnotationStrategy;
|
||||||
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.method.HandlerMethod;
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
@ -95,18 +94,8 @@ public class SaInterceptor implements HandlerInterceptor {
|
|||||||
|
|
||||||
// 这里必须确保 handler 是 HandlerMethod 类型时,才能进行注解鉴权
|
// 这里必须确保 handler 是 HandlerMethod 类型时,才能进行注解鉴权
|
||||||
if(isAnnotation && handler instanceof HandlerMethod) {
|
if(isAnnotation && handler instanceof HandlerMethod) {
|
||||||
|
|
||||||
// 获取此请求对应的 Method 处理函数
|
|
||||||
Method method = ((HandlerMethod) handler).getMethod();
|
Method method = ((HandlerMethod) handler).getMethod();
|
||||||
|
SaAnnotationStrategy.instance.checkMethodAnnotation.accept(method);
|
||||||
// 如果此 Method 或其所属 Class 标注了 @SaIgnore,则忽略掉鉴权
|
|
||||||
if(SaStrategy.instance.isAnnotationPresent.apply(method, SaIgnore.class)) {
|
|
||||||
// 注意这里直接就退出整个鉴权了,最底部的 auth.run() 路由拦截鉴权也被跳出了
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 执行注解鉴权
|
|
||||||
SaStrategy.instance.checkMethodAnnotation.accept(method);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auth 路由拦截鉴权校验
|
// Auth 路由拦截鉴权校验
|
||||||
|
@ -19,7 +19,7 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
|
|||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
import cn.dev33.satoken.exception.DisableServiceException;
|
import cn.dev33.satoken.exception.DisableServiceException;
|
||||||
import cn.dev33.satoken.exception.NotBasicAuthException;
|
import cn.dev33.satoken.exception.NotHttpBasicAuthException;
|
||||||
import cn.dev33.satoken.exception.NotLoginException;
|
import cn.dev33.satoken.exception.NotLoginException;
|
||||||
import cn.dev33.satoken.exception.NotPermissionException;
|
import cn.dev33.satoken.exception.NotPermissionException;
|
||||||
import cn.dev33.satoken.exception.NotRoleException;
|
import cn.dev33.satoken.exception.NotRoleException;
|
||||||
@ -66,8 +66,8 @@ public class HandlerException {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Http Basic 校验失败,code=903
|
// Http Basic 校验失败,code=903
|
||||||
@ExceptionHandler(NotBasicAuthException.class)
|
@ExceptionHandler(NotHttpBasicAuthException.class)
|
||||||
public SaResult handlerNotBasicAuthException(NotBasicAuthException e) {
|
public SaResult handlerNotBasicAuthException(NotHttpBasicAuthException e) {
|
||||||
return SaResult.error().setCode(903);
|
return SaResult.error().setCode(903);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user