mirror of
https://gitee.com/dromara/sa-token.git
synced 2024-12-02 03:47:50 +08:00
SaAnnotationAbstractHandler 由抽象类改为接口
This commit is contained in:
parent
834e1d5b34
commit
cd0c20793a
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.annotation.handler;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 所有注解处理器的父接口
|
||||
*
|
||||
* @author click33
|
||||
* @since 2024/8/2
|
||||
*/
|
||||
public interface SaAnnotationAbstractHandler<T extends Annotation> {
|
||||
|
||||
/**
|
||||
* 获取所要处理的注解类型
|
||||
* @return /
|
||||
*/
|
||||
Class<T> getHandlerAnnotationClass();
|
||||
|
||||
/**
|
||||
* 所需要执行的校验方法
|
||||
* @param at 注解对象
|
||||
* @param element 被标注的注解的元素引用(类或方法)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default void check(Annotation at, AnnotatedElement element) {
|
||||
checkMethod((T) at, element);
|
||||
}
|
||||
|
||||
/**
|
||||
* 所需要执行的校验方法(转换类型后)
|
||||
* @param at 注解对象
|
||||
* @param element 被标注的注解的元素引用(类或方法)
|
||||
*/
|
||||
void checkMethod(T at, AnnotatedElement element);
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.annotation.handler;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.annotation.SaCheckDisable;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaCheckDisable 的处理器
|
||||
*
|
||||
* @author click33
|
||||
* @since 2024/8/2
|
||||
*/
|
||||
public class SaCheckDisableHandler implements SaAnnotationAbstractHandler<SaCheckDisable> {
|
||||
|
||||
@Override
|
||||
public Class<SaCheckDisable> getHandlerAnnotationClass() {
|
||||
return SaCheckDisable.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaCheckDisable at, AnnotatedElement element) {
|
||||
_checkMethod(at.type(), at.value(), at.level());
|
||||
}
|
||||
|
||||
public static void _checkMethod(String type, String[] value, int level) {
|
||||
StpLogic stpLogic = SaManager.getStpLogic(type, false);
|
||||
|
||||
Object loginId = stpLogic.getLoginId();
|
||||
for (String service : value) {
|
||||
stpLogic.checkDisableLevel(loginId, service, level);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.annotation.handler;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckHttpBasic;
|
||||
import cn.dev33.satoken.httpauth.basic.SaHttpBasicUtil;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaCheckHttpBasic 的处理器
|
||||
*
|
||||
* @author click33
|
||||
* @since 2024/8/2
|
||||
*/
|
||||
public class SaCheckHttpBasicHandler implements SaAnnotationAbstractHandler<SaCheckHttpBasic> {
|
||||
|
||||
@Override
|
||||
public Class<SaCheckHttpBasic> getHandlerAnnotationClass() {
|
||||
return SaCheckHttpBasic.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaCheckHttpBasic at, AnnotatedElement element) {
|
||||
_checkMethod(at.realm(), at.account());
|
||||
}
|
||||
|
||||
public static void _checkMethod(String realm, String account) {
|
||||
SaHttpBasicUtil.check(realm, account);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.annotation.handler;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckHttpDigest;
|
||||
import cn.dev33.satoken.exception.SaTokenException;
|
||||
import cn.dev33.satoken.httpauth.digest.SaHttpDigestUtil;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaCheckHttpDigest 的处理器
|
||||
*
|
||||
* @author click33
|
||||
* @since 2024/8/2
|
||||
*/
|
||||
public class SaCheckHttpDigestHandler implements SaAnnotationAbstractHandler<SaCheckHttpDigest> {
|
||||
|
||||
@Override
|
||||
public Class<SaCheckHttpDigest> getHandlerAnnotationClass() {
|
||||
return SaCheckHttpDigest.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaCheckHttpDigest at, AnnotatedElement element) {
|
||||
_checkMethod(at.username(), at.password(), at.realm(), at.value());
|
||||
}
|
||||
|
||||
public static void _checkMethod(String username, String password, String realm, String value) {
|
||||
// 如果配置了 value,则以 value 优先
|
||||
if(SaFoxUtil.isNotEmpty(value)){
|
||||
String[] arr = value.split(":");
|
||||
if(arr.length != 2){
|
||||
throw new SaTokenException("注解参数配置错误,格式应如:username:password");
|
||||
}
|
||||
SaHttpDigestUtil.check(arr[0], arr[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果配置了 username,则分别获取参数
|
||||
if(SaFoxUtil.isNotEmpty(username)){
|
||||
SaHttpDigestUtil.check(username, password, realm);
|
||||
return;
|
||||
}
|
||||
|
||||
// 都没有配置,则根据全局配置参数进行校验
|
||||
SaHttpDigestUtil.check();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.annotation.handler;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaCheckLogin 的处理器
|
||||
*
|
||||
* @author click33
|
||||
* @since 2024/8/2
|
||||
*/
|
||||
public class SaCheckLoginHandler implements SaAnnotationAbstractHandler<SaCheckLogin> {
|
||||
|
||||
@Override
|
||||
public Class<SaCheckLogin> getHandlerAnnotationClass() {
|
||||
return SaCheckLogin.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaCheckLogin at, AnnotatedElement element) {
|
||||
_checkMethod(at.type());
|
||||
}
|
||||
|
||||
public static void _checkMethod(String type) {
|
||||
StpLogic stpLogic = SaManager.getStpLogic(type, false);
|
||||
|
||||
stpLogic.checkLogin();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.annotation.handler;
|
||||
|
||||
import cn.dev33.satoken.annotation.*;
|
||||
import cn.dev33.satoken.exception.SaTokenException;
|
||||
import cn.dev33.satoken.strategy.SaAnnotationStrategy;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 注解 SaCheckOr 的处理器
|
||||
*
|
||||
* @author click33
|
||||
* @since 2024/8/2
|
||||
*/
|
||||
public class SaCheckOrHandler implements SaAnnotationAbstractHandler<SaCheckOr> {
|
||||
|
||||
@Override
|
||||
public Class<SaCheckOr> getHandlerAnnotationClass() {
|
||||
return SaCheckOr.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaCheckOr at, AnnotatedElement element) {
|
||||
_checkMethod(at.login(), at.role(), at.permission(), at.safe(), at.httpBasic(), at.httpDigest(), at.disable(), element);
|
||||
}
|
||||
|
||||
public static void _checkMethod(
|
||||
SaCheckLogin[] login,
|
||||
SaCheckRole[] role,
|
||||
SaCheckPermission[] permission,
|
||||
SaCheckSafe[] safe,
|
||||
SaCheckHttpBasic[] httpBasic,
|
||||
SaCheckHttpDigest[] httpDigest,
|
||||
SaCheckDisable[] disable,
|
||||
AnnotatedElement element
|
||||
) {
|
||||
// 先把所有注解塞到一个 list 里
|
||||
List<Annotation> annotationList = new ArrayList<>();
|
||||
annotationList.addAll(Arrays.asList(login));
|
||||
annotationList.addAll(Arrays.asList(role));
|
||||
annotationList.addAll(Arrays.asList(permission));
|
||||
annotationList.addAll(Arrays.asList(safe));
|
||||
annotationList.addAll(Arrays.asList(disable));
|
||||
annotationList.addAll(Arrays.asList(httpBasic));
|
||||
annotationList.addAll(Arrays.asList(httpDigest));
|
||||
|
||||
// 如果 atList 为空,说明 SaCheckOr 上不包含任何注解校验,我们直接跳过即可
|
||||
if(annotationList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 逐个开始校验 >>>
|
||||
List<SaTokenException> errorList = new ArrayList<>();
|
||||
for (Annotation item : annotationList) {
|
||||
try {
|
||||
SaAnnotationStrategy.instance.annotationHandlerMap.get(item.annotationType()).check(item, element);
|
||||
// 只要有一个校验通过,就可以直接返回了
|
||||
return;
|
||||
} catch (SaTokenException e) {
|
||||
errorList.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
// 执行至此,说明所有注解校验都通过不了,此时 errorList 里面会有多个异常,我们随便抛出一个即可
|
||||
throw errorList.get(0);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.annotation.handler;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
import cn.dev33.satoken.exception.NotPermissionException;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaCheckPermission 的处理器
|
||||
*
|
||||
* @author click33
|
||||
* @since 2024/8/2
|
||||
*/
|
||||
public class SaCheckPermissionHandler implements SaAnnotationAbstractHandler<SaCheckPermission> {
|
||||
|
||||
@Override
|
||||
public Class<SaCheckPermission> getHandlerAnnotationClass() {
|
||||
return SaCheckPermission.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaCheckPermission at, AnnotatedElement element) {
|
||||
_checkMethod(at.type(), at.value(), at.mode(), at.orRole());
|
||||
}
|
||||
|
||||
public static void _checkMethod(String type, String[] value, SaMode mode, String[] orRole) {
|
||||
StpLogic stpLogic = SaManager.getStpLogic(type, false);
|
||||
|
||||
String[] permissionArray = value;
|
||||
try {
|
||||
if(mode == SaMode.AND) {
|
||||
stpLogic.checkPermissionAnd(permissionArray);
|
||||
} else {
|
||||
stpLogic.checkPermissionOr(permissionArray);
|
||||
}
|
||||
} catch (NotPermissionException e) {
|
||||
// 权限认证校验未通过,再开始角色认证校验
|
||||
for (String role : orRole) {
|
||||
String[] rArr = SaFoxUtil.convertStringToArray(role);
|
||||
// 某一项 role 认证通过,则可以提前退出了,代表通过
|
||||
if (stpLogic.hasRoleAnd(rArr)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.annotation.handler;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaCheckRole 的处理器
|
||||
*
|
||||
* @author click33
|
||||
* @since 2024/8/2
|
||||
*/
|
||||
public class SaCheckRoleHandler implements SaAnnotationAbstractHandler<SaCheckRole> {
|
||||
|
||||
@Override
|
||||
public Class<SaCheckRole> getHandlerAnnotationClass() {
|
||||
return SaCheckRole.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaCheckRole at, AnnotatedElement element) {
|
||||
_checkMethod(at.type(), at.value(), at.mode());
|
||||
}
|
||||
|
||||
public static void _checkMethod(String type, String[] value, SaMode mode) {
|
||||
StpLogic stpLogic = SaManager.getStpLogic(type, false);
|
||||
|
||||
String[] roleArray = value;
|
||||
if(mode == SaMode.AND) {
|
||||
stpLogic.checkRoleAnd(roleArray);
|
||||
} else {
|
||||
stpLogic.checkRoleOr(roleArray);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.annotation.handler;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.annotation.SaCheckSafe;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaCheckSafe 的处理器
|
||||
*
|
||||
* @author click33
|
||||
* @since 2024/8/2
|
||||
*/
|
||||
public class SaCheckSafeHandler implements SaAnnotationAbstractHandler<SaCheckSafe> {
|
||||
|
||||
@Override
|
||||
public Class<SaCheckSafe> getHandlerAnnotationClass() {
|
||||
return SaCheckSafe.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaCheckSafe at, AnnotatedElement element) {
|
||||
_checkMethod(at.type(), at.value());
|
||||
}
|
||||
|
||||
public static void _checkMethod(String type, String value) {
|
||||
StpLogic stpLogic = SaManager.getStpLogic(type, false);
|
||||
|
||||
stpLogic.checkSafe(value);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.annotation.handler;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.dev33.satoken.router.SaRouter;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaIgnore 的处理器
|
||||
*
|
||||
* @author click33
|
||||
* @since 2024/8/2
|
||||
*/
|
||||
public class SaIgnoreHandler implements SaAnnotationAbstractHandler<SaIgnore> {
|
||||
|
||||
@Override
|
||||
public Class<SaIgnore> getHandlerAnnotationClass() {
|
||||
return SaIgnore.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaIgnore at, AnnotatedElement element) {
|
||||
_checkMethod();
|
||||
}
|
||||
|
||||
public static void _checkMethod() {
|
||||
SaRouter.stop();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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.strategy;
|
||||
|
||||
import cn.dev33.satoken.annotation.*;
|
||||
import cn.dev33.satoken.annotation.handler.*;
|
||||
import cn.dev33.satoken.fun.strategy.SaCheckMethodAnnotationFunction;
|
||||
import cn.dev33.satoken.fun.strategy.SaGetAnnotationFunction;
|
||||
import cn.dev33.satoken.listener.SaTokenEventCenter;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Sa-Token 注解鉴权相关策略
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.39.0
|
||||
*/
|
||||
public final class SaAnnotationStrategy {
|
||||
|
||||
private SaAnnotationStrategy() {
|
||||
registerDefaultAnnotationHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局单例引用
|
||||
*/
|
||||
public static final SaAnnotationStrategy instance = new SaAnnotationStrategy();
|
||||
|
||||
|
||||
// ----------------------- 所有策略
|
||||
|
||||
/**
|
||||
* 注解处理器集合
|
||||
*/
|
||||
public Map<Class<?>, SaAnnotationAbstractHandler<?>> annotationHandlerMap = new LinkedHashMap<>();
|
||||
|
||||
/**
|
||||
* 注册所有默认的注解处理器
|
||||
*/
|
||||
public void registerDefaultAnnotationHandler() {
|
||||
annotationHandlerMap.put(SaIgnore.class, new SaIgnoreHandler());
|
||||
annotationHandlerMap.put(SaCheckLogin.class, new SaCheckLoginHandler());
|
||||
annotationHandlerMap.put(SaCheckRole.class, new SaCheckRoleHandler());
|
||||
annotationHandlerMap.put(SaCheckPermission.class, new SaCheckPermissionHandler());
|
||||
annotationHandlerMap.put(SaCheckSafe.class, new SaCheckSafeHandler());
|
||||
annotationHandlerMap.put(SaCheckDisable.class, new SaCheckDisableHandler());
|
||||
annotationHandlerMap.put(SaCheckHttpBasic.class, new SaCheckHttpBasicHandler());
|
||||
annotationHandlerMap.put(SaCheckHttpDigest.class, new SaCheckHttpDigestHandler());
|
||||
annotationHandlerMap.put(SaCheckOr.class, new SaCheckOrHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册一个注解处理器
|
||||
*/
|
||||
public void registerAnnotationHandler(SaAnnotationAbstractHandler<?> handler) {
|
||||
annotationHandlerMap.put(handler.getHandlerAnnotationClass(), handler);
|
||||
SaTokenEventCenter.doRegisterAnnotationHandler(handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册一个注解处理器,到首位
|
||||
*/
|
||||
public void registerAnnotationHandlerToFirst(SaAnnotationAbstractHandler<?> handler) {
|
||||
Map<Class<?>, SaAnnotationAbstractHandler<?>> newMap = new LinkedHashMap<>();
|
||||
newMap.put(handler.getHandlerAnnotationClass(), handler);
|
||||
newMap.putAll(annotationHandlerMap);
|
||||
this.annotationHandlerMap = newMap;
|
||||
SaTokenEventCenter.doRegisterAnnotationHandler(handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除一个注解处理器
|
||||
*/
|
||||
public void removeAnnotationHandler(Class<?> cls) {
|
||||
annotationHandlerMap.remove(cls);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对一个 [Method] 对象进行注解校验 (注解鉴权内部实现)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public SaCheckMethodAnnotationFunction checkMethodAnnotation = (method) -> {
|
||||
// 遍历所有的注解处理器,检查此 method 是否具有这些指定的注解
|
||||
for (Map.Entry<Class<?>, SaAnnotationAbstractHandler<?>> entry: annotationHandlerMap.entrySet()) {
|
||||
|
||||
// 先校验 Method 所属 Class 上的注解
|
||||
Annotation classTakeAnnotation = instance.getAnnotation.apply(method.getDeclaringClass(), (Class<Annotation>)entry.getKey());
|
||||
if(classTakeAnnotation != null) {
|
||||
entry.getValue().check(classTakeAnnotation, method.getDeclaringClass());
|
||||
}
|
||||
|
||||
// 再校验 Method 上的注解
|
||||
Annotation methodTakeAnnotation = instance.getAnnotation.apply(method, (Class<Annotation>)entry.getKey());
|
||||
if(methodTakeAnnotation != null) {
|
||||
entry.getValue().check(methodTakeAnnotation, method);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 从元素上获取注解
|
||||
*/
|
||||
public SaGetAnnotationFunction getAnnotation = (element, annotationClass)->{
|
||||
// 默认使用jdk的注解处理器
|
||||
return element.getAnnotation(annotationClass);
|
||||
};
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package com.pj.cases.test;
|
||||
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
import com.pj.satoken.custom_annotation.CheckAccount;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@ -15,6 +16,7 @@ public class TestController {
|
||||
|
||||
// 测试 浏览器访问: http://localhost:8081/test/test
|
||||
@RequestMapping("test")
|
||||
@CheckAccount(name = "sa", pwd = "123456")
|
||||
public SaResult test() {
|
||||
System.out.println("------------进来了");
|
||||
return SaResult.ok();
|
||||
|
@ -0,0 +1,33 @@
|
||||
package com.pj.satoken.custom_annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 账号校验:在标注一个方法上时,要求前端必须提交相应的账号密码参数才能访问方法。
|
||||
*
|
||||
* @author click33
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE})
|
||||
public @interface CheckAccount {
|
||||
|
||||
/**
|
||||
* 需要校验的账号
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* 需要校验的密码
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
String pwd();
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.pj.satoken.custom_annotation;
|
||||
|
||||
import cn.dev33.satoken.util.SaTokenConsts;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 二级认证校验(User版):客户端必须完成二级认证之后,才能进入该方法,否则将被抛出异常。
|
||||
*
|
||||
* <p> 可标注在方法、类上(效果等同于标注在此类的所有方法上)。
|
||||
*
|
||||
* @author click33
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
public @interface SaUserCheckSafe {
|
||||
|
||||
/**
|
||||
* 要校验的服务
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
String value() default SaTokenConsts.DEFAULT_SAFE_AUTH_SERVICE;
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package com.pj.satoken.custom_annotation.handler;
|
||||
|
||||
import cn.dev33.satoken.annotation.handler.SaAnnotationAbstractHandler;
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.exception.SaTokenException;
|
||||
import com.pj.satoken.custom_annotation.CheckAccount;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 CheckAccount 的处理器
|
||||
*
|
||||
* @author click33
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class CheckAccountHandler implements SaAnnotationAbstractHandler<CheckAccount> {
|
||||
|
||||
// 指定这个处理器要处理哪个注解
|
||||
@Override
|
||||
public Class<CheckAccount> getHandlerAnnotationClass() {
|
||||
return CheckAccount.class;
|
||||
}
|
||||
|
||||
// 每次请求校验注解时,会执行的方法
|
||||
@Override
|
||||
public void checkMethod(CheckAccount at, AnnotatedElement element) {
|
||||
// 获取前端请求提交的参数
|
||||
String name = SaHolder.getRequest().getParamNotNull("name");
|
||||
String pwd = SaHolder.getRequest().getParamNotNull("pwd");
|
||||
|
||||
// 与注解中指定的值相比较
|
||||
if(name.equals(at.name()) && pwd.equals(at.pwd()) ) {
|
||||
// 校验通过,什么也不做
|
||||
} else {
|
||||
// 校验不通过,则抛出异常
|
||||
throw new SaTokenException("账号或密码错误,未通过校验");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.pj.satoken.custom_annotation.handler;
|
||||
|
||||
import cn.dev33.satoken.annotation.handler.SaAnnotationAbstractHandler;
|
||||
import cn.dev33.satoken.annotation.handler.SaCheckLoginHandler;
|
||||
import com.pj.satoken.StpUserUtil;
|
||||
import com.pj.satoken.custom_annotation.SaUserCheckLogin;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaUserCheckLogin 的处理器
|
||||
*
|
||||
* @author click33
|
||||
*/
|
||||
@Component
|
||||
public class SaUserCheckLoginHandler implements SaAnnotationAbstractHandler<SaUserCheckLogin> {
|
||||
|
||||
@Override
|
||||
public Class<SaUserCheckLogin> getHandlerAnnotationClass() {
|
||||
return SaUserCheckLogin.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaUserCheckLogin at, AnnotatedElement element) {
|
||||
SaCheckLoginHandler._checkMethod(StpUserUtil.TYPE);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.pj.satoken.custom_annotation.handler;
|
||||
|
||||
import cn.dev33.satoken.annotation.handler.SaAnnotationAbstractHandler;
|
||||
import cn.dev33.satoken.annotation.handler.SaCheckPermissionHandler;
|
||||
import com.pj.satoken.StpUserUtil;
|
||||
import com.pj.satoken.custom_annotation.SaUserCheckPermission;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaUserCheckPermission 的处理器
|
||||
*
|
||||
* @author click33
|
||||
*/
|
||||
@Component
|
||||
public class SaUserCheckPermissionHandler implements SaAnnotationAbstractHandler<SaUserCheckPermission> {
|
||||
|
||||
@Override
|
||||
public Class<SaUserCheckPermission> getHandlerAnnotationClass() {
|
||||
return SaUserCheckPermission.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaUserCheckPermission at, AnnotatedElement element) {
|
||||
SaCheckPermissionHandler._checkMethod(StpUserUtil.TYPE, at.value(), at.mode(), at.orRole());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.pj.satoken.custom_annotation.handler;
|
||||
|
||||
import cn.dev33.satoken.annotation.handler.SaAnnotationAbstractHandler;
|
||||
import cn.dev33.satoken.annotation.handler.SaCheckRoleHandler;
|
||||
import com.pj.satoken.StpUserUtil;
|
||||
import com.pj.satoken.custom_annotation.SaUserCheckRole;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaUserCheckRole 的处理器
|
||||
*
|
||||
* @author click33
|
||||
*/
|
||||
@Component
|
||||
public class SaUserCheckRoleHandler implements SaAnnotationAbstractHandler<SaUserCheckRole> {
|
||||
|
||||
@Override
|
||||
public Class<SaUserCheckRole> getHandlerAnnotationClass() {
|
||||
return SaUserCheckRole.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaUserCheckRole at, AnnotatedElement element) {
|
||||
SaCheckRoleHandler._checkMethod(StpUserUtil.TYPE, at.value(), at.mode());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.pj.satoken.custom_annotation.handler;
|
||||
|
||||
import cn.dev33.satoken.annotation.handler.SaAnnotationAbstractHandler;
|
||||
import cn.dev33.satoken.annotation.handler.SaCheckSafeHandler;
|
||||
import com.pj.satoken.StpUserUtil;
|
||||
import com.pj.satoken.custom_annotation.SaUserCheckSafe;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaUserCheckPermission 的处理器
|
||||
*
|
||||
* @author click33
|
||||
*/
|
||||
@Component
|
||||
public class SaUserCheckSafeHandler implements SaAnnotationAbstractHandler<SaUserCheckSafe> {
|
||||
|
||||
@Override
|
||||
public Class<SaUserCheckSafe> getHandlerAnnotationClass() {
|
||||
return SaUserCheckSafe.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaUserCheckSafe at, AnnotatedElement element) {
|
||||
SaCheckSafeHandler._checkMethod(StpUserUtil.TYPE, at.value());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.pj.satoken.merge_annotation;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import com.pj.satoken.StpUserUtil;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 登录认证(User版):只有登录之后才能进入该方法
|
||||
* <p> 可标注在函数、类上(效果等同于标注在此类的所有方法上)
|
||||
* @author click33
|
||||
*
|
||||
*/
|
||||
@SaCheckLogin(type = StpUserUtil.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE})
|
||||
public @interface SaUserCheckLogin {
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.pj.satoken.merge_annotation;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
import com.pj.satoken.StpUserUtil;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 权限认证(User版):必须具有指定权限才能进入该方法
|
||||
* <p> 可标注在函数、类上(效果等同于标注在此类的所有方法上)
|
||||
* @author click33
|
||||
*
|
||||
*/
|
||||
@SaCheckPermission(type = StpUserUtil.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE})
|
||||
public @interface SaUserCheckPermission {
|
||||
|
||||
/**
|
||||
* 需要校验的权限码
|
||||
* @return 需要校验的权限码
|
||||
*/
|
||||
@AliasFor(annotation = SaCheckPermission.class)
|
||||
String [] value() default {};
|
||||
|
||||
/**
|
||||
* 验证模式:AND | OR,默认AND
|
||||
* @return 验证模式
|
||||
*/
|
||||
@AliasFor(annotation = SaCheckPermission.class)
|
||||
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 /
|
||||
*/
|
||||
@AliasFor(annotation = SaCheckPermission.class)
|
||||
String[] orRole() default {};
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.pj.satoken.merge_annotation;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
import com.pj.satoken.StpUserUtil;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 角色认证(User版):必须具有指定角色标识才能进入该方法
|
||||
* <p> 可标注在函数、类上(效果等同于标注在此类的所有方法上)
|
||||
* @author click33
|
||||
*
|
||||
*/
|
||||
@SaCheckRole(type = StpUserUtil.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE})
|
||||
public @interface SaUserCheckRole {
|
||||
|
||||
/**
|
||||
* 需要校验的角色标识
|
||||
* @return 需要校验的角色标识
|
||||
*/
|
||||
@AliasFor(annotation = SaCheckRole.class)
|
||||
String [] value() default {};
|
||||
|
||||
/**
|
||||
* 验证模式:AND | OR,默认AND
|
||||
* @return 验证模式
|
||||
*/
|
||||
@AliasFor(annotation = SaCheckRole.class)
|
||||
SaMode mode() default SaMode.AND;
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.pj.satoken.merge_annotation;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckSafe;
|
||||
import cn.dev33.satoken.util.SaTokenConsts;
|
||||
import com.pj.satoken.StpUserUtil;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 二级认证校验(User版):客户端必须完成二级认证之后,才能进入该方法,否则将被抛出异常。
|
||||
*
|
||||
* <p> 可标注在方法、类上(效果等同于标注在此类的所有方法上)。
|
||||
*
|
||||
* @author click33
|
||||
*/
|
||||
@SaCheckSafe(type = StpUserUtil.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
public @interface SaUserCheckSafe {
|
||||
|
||||
/**
|
||||
* 要校验的服务
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
String value() default SaTokenConsts.DEFAULT_SAFE_AUTH_SERVICE;
|
||||
|
||||
}
|
199
sa-token-doc/fun/custom-annotations.md
Normal file
199
sa-token-doc/fun/custom-annotations.md
Normal file
@ -0,0 +1,199 @@
|
||||
# 自定义注解
|
||||
|
||||
如果框架内置的注解无法满足你的业务需求,你还可以自定义注解注入到框架中。
|
||||
|
||||
---
|
||||
|
||||
### 1、自定义注解
|
||||
|
||||
假设有以下业务需求
|
||||
|
||||
> [!INFO| label:需求场景]
|
||||
> 自定义一个注解 `@CheckAccount`,具有 `name`、`pwd` 两个字段,在标注一个方法上时,要求前端必须提交相应的账号密码参数才能访问方法。
|
||||
|
||||
|
||||
#### 1.1、第一步,创建一个注解
|
||||
|
||||
``` java
|
||||
/**
|
||||
* 账号校验:在标注一个方法上时,要求前端必须提交相应的账号密码参数才能访问方法。
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE})
|
||||
public @interface CheckAccount {
|
||||
|
||||
/**
|
||||
* 需要校验的账号
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* 需要校验的密码
|
||||
*/
|
||||
String pwd();
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.2、第二步,创建注解处理器
|
||||
|
||||
实现 `SaAnnotationAbstractHandler` 接口,指定泛型为刚才自定义的注解
|
||||
|
||||
``` java
|
||||
/**
|
||||
* 注解 CheckAccount 的处理器
|
||||
*/
|
||||
@Component
|
||||
public class CheckAccountHandler implements SaAnnotationAbstractHandler<CheckAccount> {
|
||||
|
||||
// 指定这个处理器要处理哪个注解
|
||||
@Override
|
||||
public Class<CheckAccount> getHandlerAnnotationClass() {
|
||||
return CheckAccount.class;
|
||||
}
|
||||
|
||||
// 每次请求校验注解时,会执行的方法
|
||||
@Override
|
||||
public void checkMethod(CheckAccount at, AnnotatedElement element) {
|
||||
// 获取前端请求提交的参数
|
||||
String name = SaHolder.getRequest().getParamNotNull("name");
|
||||
String pwd = SaHolder.getRequest().getParamNotNull("pwd");
|
||||
|
||||
// 与注解中指定的值相比较
|
||||
if(name.equals(at.name()) && pwd.equals(at.pwd()) ) {
|
||||
// 校验通过,什么也不做
|
||||
} else {
|
||||
// 校验不通过,则抛出异常
|
||||
throw new SaTokenException("账号或密码错误,未通过校验");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
参考上述代码,实现类上指定了 `@Component` 注解,使其可以在 ioc 环境下(如 Spring)被自动扫描注册 Sa-Token 中,
|
||||
如果你的项目属于非 ioc 环境,则需要手动将其注册到 Sa-Token 框架中:
|
||||
``` java
|
||||
SaAnnotationStrategy.instance.registerAnnotationHandler(new CheckAccountHandler());
|
||||
```
|
||||
|
||||
#### 1.3、测试自定义的注解
|
||||
|
||||
我们在一个请求接口上指定这个注解,来测试一下效果
|
||||
|
||||
``` java
|
||||
@RestController
|
||||
@RequestMapping("/test/")
|
||||
public class TestController {
|
||||
|
||||
@RequestMapping("test")
|
||||
@CheckAccount(name = "sa", pwd = "123456")
|
||||
public SaResult test() {
|
||||
System.out.println("------------进来了");
|
||||
return SaResult.ok();
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
启动项目,使用浏览器访问此接口。
|
||||
|
||||
先来个错误的账号密码访问测试一下:[http://localhost:8081/test/test?name=sa&pwd=123](http://localhost:8081/test/test?name=sa&pwd=123)
|
||||
|
||||
返回结果:
|
||||
|
||||
``` js
|
||||
{
|
||||
"code": 500,
|
||||
"msg": "账号或密码错误,未通过校验",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
使用正确账号密码测试访问:[http://localhost:8081/test/test?name=sa&pwd=123456](http://localhost:8081/test/test?name=sa&pwd=123456)
|
||||
|
||||
返回结果:
|
||||
|
||||
``` js
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "ok",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 2、使用自定义注解优化多账号鉴权
|
||||
|
||||
在之前的 [ 多账号鉴权 ] 章节,我们介绍了利用 “spring 注解处理器” 达到注解合并的目的,从而简化多账号体系下的注解鉴权写法。
|
||||
|
||||
此种方案比较简单,但是也有一些缺点。
|
||||
- 1、强依赖 Spring,无法在非 Spring 环境中使用。
|
||||
- 2、注解递归检查可能会造成一些性能下降。
|
||||
- 3、扩展性较低,只能略微简化框架内置好的注解写法,无法灵活扩展功能。
|
||||
|
||||
此处我们再演示一种方案,使用自定义注解的方式达到相同的目的。
|
||||
|
||||
|
||||
#### 2.1、首先定义注解
|
||||
|
||||
``` java
|
||||
/**
|
||||
* 登录认证(User版):只有登录之后才能进入该方法
|
||||
* <p> 可标注在函数、类上(效果等同于标注在此类的所有方法上)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE})
|
||||
public @interface SaUserCheckLogin {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2、定义注解处理器
|
||||
``` java
|
||||
/**
|
||||
* 注解 SaUserCheckLogin 的处理器
|
||||
*/
|
||||
@Component
|
||||
public class SaUserCheckLoginHandler implements SaAnnotationAbstractHandler<SaUserCheckLogin> {
|
||||
|
||||
@Override
|
||||
public Class<SaUserCheckLogin> getHandlerAnnotationClass() {
|
||||
return SaUserCheckLogin.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaUserCheckLogin at, AnnotatedElement element) {
|
||||
SaCheckLoginHandler._checkMethod(StpUserUtil.TYPE);
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.3、使用新注解
|
||||
接下来就可以使用我们的自定义注解了:
|
||||
|
||||
``` java
|
||||
// 使用 @SaUserCheckLogin 的效果等同于使用:@SaCheckLogin(type = "user")
|
||||
@SaUserCheckLogin
|
||||
@RequestMapping("info")
|
||||
public String info() {
|
||||
return "查询用户信息";
|
||||
}
|
||||
```
|
||||
|
||||
注:其它注解 `@SaCheckRole("xxx")`、`@SaCheckPermission("xxx")` 同理, 完整示例参考 Gitee 代码:
|
||||
[自定义注解](https://gitee.com/dromara/sa-token/tree/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/custom_annotation)。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user