v1.11.0 新特性:AOP注解鉴权

This commit is contained in:
shengzhang
2021-01-09 17:24:44 +08:00
parent 1028ac0fe6
commit fbff086ed9
10 changed files with 233 additions and 57 deletions

12
sa-token-aop/.gitignore vendored Normal file
View File

@@ -0,0 +1,12 @@
target/
node_modules/
bin/
.settings/
unpackage/
.classpath
.project
.factorypath
.idea/

35
sa-token-aop/pom.xml Normal file
View File

@@ -0,0 +1,35 @@
<?xml version='1.0' encoding='utf-8'?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-parent</artifactId>
<version>1.10.0</version>
</parent>
<packaging>jar</packaging>
<name>sa-token-aop</name>
<artifactId>sa-token-aop</artifactId>
<description>sa-token authentication by spring-aop</description>
<dependencies>
<!-- sa-token-spring-boot-starter -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.10.0</version>
</dependency>
<!-- spring-boot-starter-aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,67 @@
package cn.dev33.satoken.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
/**
* sa-token 基于 Spring Aop 的注解鉴权
* @author kong
*/
@Aspect
@Component
public class SaCheckAspect {
/**
* 底层的 StpLogic 对象
*/
public StpLogic stpLogic = null;
/**
* 创建,并指定一个默认的 StpLogic
*/
public SaCheckAspect() {
this.stpLogic = StpUtil.stpLogic;
}
/**
* 定义AOP签名 --> (切入所有使用sa-token鉴权注解的方法)
*/
public static final String POINTCUT_SIGN = "@within(cn.dev33.satoken.annotation.SaCheckLogin) || @annotation(cn.dev33.satoken.annotation.SaCheckLogin) || "
+ "@within(cn.dev33.satoken.annotation.SaCheckRole) || @annotation(cn.dev33.satoken.annotation.SaCheckRole) || "
+ "@within(cn.dev33.satoken.annotation.SaCheckPermission) || @annotation(cn.dev33.satoken.annotation.SaCheckPermission)";
/**
* 声明AOP签名
*/
@Pointcut(POINTCUT_SIGN)
public void pointcut() {
}
/**
* 环绕切入
* @param joinPoint 切面对象
* @return 底层方法执行后的返回值
* @throws Throwable
*/
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// 注解鉴权
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
stpLogic.checkMethodAnnotation(signature.getMethod());
try {
// 执行原有逻辑
Object obj = joinPoint.proceed();
return obj;
} catch (Throwable e) {
throw e;
}
}
}

View File

@@ -0,0 +1 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.dev33.satoken.aop.SaCheckAspect

View File

@@ -1,5 +1,6 @@
package cn.dev33.satoken.stp;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -9,6 +10,10 @@ import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import cn.dev33.satoken.SaTokenManager;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaMode;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.exception.NotLoginException;
@@ -1042,7 +1047,65 @@ public class StpLogic {
}
// =================== 注解鉴权 ===================
/**
* 对一个Method对象进行注解检查注解鉴权内部实现
* @param method Method对象
*/
public void checkMethodAnnotation(Method method) {
// ----------- 验证登录
if(method.isAnnotationPresent(SaCheckLogin.class) || method.getDeclaringClass().isAnnotationPresent(SaCheckLogin.class)) {
this.checkLogin();
}
// ----------- 验证角色
// 验证方法上的
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);
}
}
// 验证通过
}

View File

@@ -52,6 +52,13 @@
<artifactId>commons-pool2</artifactId>
</dependency> -->
<!-- sa-token整合SpringAop实现注解鉴权 -->
<!-- <dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-aop</artifactId>
<version>1.10.0</version>
</dependency> -->
<!-- @ConfigurationProperties -->
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -3,6 +3,7 @@ package com.pj.test;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@@ -218,6 +219,18 @@ public class TestController {
}
@Autowired
TestService TestService;
// 测试AOP注解鉴权 http://localhost:8081/test/testAOP
@RequestMapping("testAOP")
public AjaxJson testAOP() {
System.out.println("testAOP");
TestService.getList();
return AjaxJson.getSuccess();
}
// 测试 浏览器访问: http://localhost:8081/test/test
@RequestMapping("test")
public AjaxJson test() {

View File

@@ -0,0 +1,26 @@
package com.pj.test;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import cn.dev33.satoken.annotation.SaCheckLogin;
/**
* 用来测试AOP注解鉴权
* @author kong
*
*/
@Service
//@SaCheckLogin
public class TestService {
@SaCheckLogin
public List<String> getList() {
System.out.println("getList");
return new ArrayList<String>();
}
}

View File

@@ -2,11 +2,11 @@
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>sa-token 官方文档</title>
<title>sa-token</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="Description">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta name="keywords" content="sa-token|sa-token框架|sa-token文档|sa-token在线文档|权限认证框架">
<meta name="keywords" content="sa-token|sa-token框架|sa-token文档|sa-token在线文档|sa-token官方文档|权限认证框架">
<meta name="description" content="sa-token是一个JavaWeb权限认证框架功能全面上手简单登录验证、权限验证、Session会话、踢人下线、集成Redis、前后台分离、模拟他人账号、多账号体系、注解式鉴权、花式token、自动续签、同端互斥登录、会话治理、Spring集成...,零配置开箱即用,覆盖所有应用场景,你所需要的功能,这里都有">
<link rel="stylesheet" href="https://unpkg.zhimg.com/docsify@4.11.3/lib/themes/vue.css">
<link rel="stylesheet" href="./lib/index.css">

View File

@@ -1,15 +1,13 @@
package cn.dev33.satoken.interceptor;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaMode;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
@@ -52,56 +50,10 @@ public class SaCheckInterceptor implements HandlerInterceptor {
if (handler instanceof HandlerMethod == false) {
return true;
}
HandlerMethod method = (HandlerMethod ) handler;
Method method = ((HandlerMethod) handler).getMethod();
// ----------- 验证登录
if(method.hasMethodAnnotation(SaCheckLogin.class) || method.getBeanType().isAnnotationPresent(SaCheckLogin.class)) {
stpLogic.checkLogin();
}
// ----------- 验证角色
// 验证方法上的
SaCheckRole scr = method.getMethodAnnotation(SaCheckRole.class);
if(scr != null) {
String[] roleArray = scr.value();
if(scr.mode() == SaMode.AND) {
stpLogic.checkRoleAnd(roleArray); // 必须全部都有
} else {
stpLogic.checkRoleOr(roleArray); // 有一个就行了
}
}
// 验证类上的
scr = method.getBeanType().getAnnotation(SaCheckRole.class);
if(scr != null) {
String[] roleArray = scr.value();
if(scr.mode() == SaMode.AND) {
stpLogic.checkRoleAnd(roleArray); // 必须全部都有
} else {
stpLogic.checkRoleOr(roleArray); // 有一个就行了
}
}
// ----------- 验证权限
// 验证方法上的
SaCheckPermission scp = method.getMethodAnnotation(SaCheckPermission.class);
if(scp != null) {
String[] permissionArray = scp.value();
if(scp.mode() == SaMode.AND) {
stpLogic.checkPermissionAnd(permissionArray); // 必须全部都有
} else {
stpLogic.checkPermissionOr(permissionArray); // 有一个就行了
}
}
// 验证类上的
scp = method.getBeanType().getAnnotation(SaCheckPermission.class);
if(scp != null) {
String[] permissionArray = scp.value();
if(scp.mode() == SaMode.AND) {
stpLogic.checkPermissionAnd(permissionArray); // 必须全部都有
} else {
stpLogic.checkPermissionOr(permissionArray); // 有一个就行了
}
}
// 进行验证
stpLogic.checkMethodAnnotation(method);
// 通过验证
return true;