diff --git a/README.md b/README.md
index b10d1a1d..c68b5965 100644
--- a/README.md
+++ b/README.md
@@ -21,6 +21,7 @@
- 持久层扩展(集成redis)
- 多账号认证体系(比如一个商城项目的user表和admin表)
- 无cookie模式(APP、小程序等前后台分离场景)
+- 注解式鉴权(优雅的将鉴权与业务代码分离)
- 零配置与Spring等框架集成
- ...
diff --git a/sa-token-demo-springboot/pom.xml b/sa-token-demo-springboot/pom.xml
index 575bf84d..8a36dcc1 100644
--- a/sa-token-demo-springboot/pom.xml
+++ b/sa-token-demo-springboot/pom.xml
@@ -25,11 +25,11 @@
spring-boot-starter-aop
-
+
cn.dev33
sa-token
- 1.0.1
+ 1.0.2
diff --git a/sa-token-demo-springboot/src/main/java/com/pj/satoken/MySaTokenConfig.java b/sa-token-demo-springboot/src/main/java/com/pj/satoken/MySaTokenConfig.java
index 846eff03..cc2c8265 100644
--- a/sa-token-demo-springboot/src/main/java/com/pj/satoken/MySaTokenConfig.java
+++ b/sa-token-demo-springboot/src/main/java/com/pj/satoken/MySaTokenConfig.java
@@ -1,18 +1,18 @@
-//package com.pj.satoken;
-//
-//import org.springframework.context.annotation.Bean;
-//import org.springframework.context.annotation.Configuration;
-//import org.springframework.context.annotation.Primary;
-//
-//import cn.dev33.satoken.config.SaTokenConfig;
-//
-///**
-// * sa-token代码方式进行配置
-// */
-//@Configuration
-//public class MySaTokenConfig {
-//
-// // 获取配置Bean
+package com.pj.satoken;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+import cn.dev33.satoken.annotation.SaCheckInterceptor;
+
+/**
+ * sa-token代码方式进行配置
+ */
+@Configuration
+public class MySaTokenConfig extends WebMvcConfigurationSupport {
+
+ // 获取配置Bean (以代码的方式配置sa-token)
// @Primary
// @Bean(name="MySaTokenConfig")
// public SaTokenConfig getSaTokenConfig() {
@@ -25,5 +25,11 @@
// config.setIsV(true); // 是否在初始化配置时打印版本字符画
// return config;
// }
-//
-//}
+
+ // 注册sa-token的拦截器,打开注解式鉴权功能
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(new SaCheckInterceptor()).addPathPatterns("/**");
+ }
+
+}
diff --git a/sa-token-demo-springboot/src/main/java/com/pj/test/TestController.java b/sa-token-demo-springboot/src/main/java/com/pj/test/TestController.java
index 064c60d4..c8bed11b 100644
--- a/sa-token-demo-springboot/src/main/java/com/pj/test/TestController.java
+++ b/sa-token-demo-springboot/src/main/java/com/pj/test/TestController.java
@@ -4,6 +4,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
+import cn.dev33.satoken.annotation.SaCheckLogin;
+import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.session.SaSessionCustomUtil;
import cn.dev33.satoken.stp.StpUtil;
@@ -86,5 +88,21 @@ public class TestController {
}
+ // 测试注解式鉴权, 浏览器访问: http://localhost:8081/test/at_check
+ @SaCheckLogin // 注解式鉴权:当前会话必须登录才能通过
+ @SaCheckPermission("user-add") // 注解式鉴权:当前会话必须具有指定权限才能通过
+ @RequestMapping("at_check")
+ public AjaxJson at_check() {
+ System.out.println("======================= 进入方法,测试注解鉴权接口 ========================= ");
+ System.out.println("只有通过注解鉴权,才能进入此方法");
+ return AjaxJson.getSuccess();
+ }
+
+
+ @SaCheckLogin // 注解式鉴权:当前会话必须登录才能通过
+ @RequestMapping("getInfo")
+ public String getInfo() {
+ return "用户信息";
+ }
}
diff --git a/sa-token-dev/pom.xml b/sa-token-dev/pom.xml
index 90a11e14..f9bfe2db 100644
--- a/sa-token-dev/pom.xml
+++ b/sa-token-dev/pom.xml
@@ -2,9 +2,12 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
+
+
cn.dev33
sa-token-dev
- 0.0.1-SNAPSHOT
+ jar
+ 1.0.2
diff --git a/sa-token-dev/src/main/java/cn/dev33/satoken/annotation/SaCheckInterceptor.java b/sa-token-dev/src/main/java/cn/dev33/satoken/annotation/SaCheckInterceptor.java
new file mode 100644
index 00000000..6a9bc440
--- /dev/null
+++ b/sa-token-dev/src/main/java/cn/dev33/satoken/annotation/SaCheckInterceptor.java
@@ -0,0 +1,72 @@
+package cn.dev33.satoken.annotation;
+
+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.stp.StpUtil;
+
+/**
+ * 注解式鉴权 - 拦截器
+ */
+public class SaCheckInterceptor implements HandlerInterceptor {
+
+ // 每次请求之前触发
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+
+ // 获取处理method
+ if (handler instanceof HandlerMethod == false) {
+ return true;
+ }
+ HandlerMethod method = (HandlerMethod ) handler;
+
+ // 验证登录
+ if(method.hasMethodAnnotation(SaCheckLogin.class) || method.getBeanType().isAnnotationPresent(SaCheckLogin.class)) {
+ StpUtil.getLoginId();
+ }
+
+ // 获取权限注解
+ SaCheckPermission scp = method.getMethodAnnotation(SaCheckPermission.class);
+ if(scp == null) {
+ scp = method.getBeanType().getAnnotation(SaCheckPermission.class);
+ }
+ if(scp == null) {
+ return true;
+ }
+
+ // 开始验证权限
+ Object[] codeArray = concatABC(scp.value(), scp.valueInt(), scp.valueLong());
+ if(scp.isAnd()) {
+ StpUtil.checkPermissionAnd(codeArray); // 必须全部都有
+ } else {
+ StpUtil.checkPermissionOr(codeArray); // 有一个就行了
+ }
+
+ return true;
+ }
+
+
+ // 合并三个数组
+ private Object[] concatABC(String[] a, int[] b, long[] c) {
+ // 循环赋值
+ Object[] d = new Object[a.length + b.length + c.length];
+ for (int i = 0; i < a.length; i++) {
+ d[i] = a[i];
+ }
+ for (int i = 0; i < b.length; i++) {
+ d[a.length + i] = b[i];
+ }
+ for (int i = 0; i < c.length; i++) {
+ d[a.length + b.length + i] = c[i];
+ }
+ return d;
+ }
+
+
+
+
+}
diff --git a/sa-token-dev/src/main/java/cn/dev33/satoken/annotation/SaCheckLogin.java b/sa-token-dev/src/main/java/cn/dev33/satoken/annotation/SaCheckLogin.java
new file mode 100644
index 00000000..48da60ef
--- /dev/null
+++ b/sa-token-dev/src/main/java/cn/dev33/satoken/annotation/SaCheckLogin.java
@@ -0,0 +1,15 @@
+package cn.dev33.satoken.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 标注一个路由方法,当前会话必须已登录才能通过
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD, ElementType.TYPE })
+public @interface SaCheckLogin {
+
+}
diff --git a/sa-token-dev/src/main/java/cn/dev33/satoken/annotation/SaCheckPermission.java b/sa-token-dev/src/main/java/cn/dev33/satoken/annotation/SaCheckPermission.java
new file mode 100644
index 00000000..b5ec8b68
--- /dev/null
+++ b/sa-token-dev/src/main/java/cn/dev33/satoken/annotation/SaCheckPermission.java
@@ -0,0 +1,39 @@
+package cn.dev33.satoken.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 标注一个路由方法,当前会话必须具有指定权限才可以通过
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD,ElementType.TYPE})
+public @interface SaCheckPermission {
+
+ /**
+ * 权限码数组 ,String类型
+ * @return .
+ */
+ String [] value() default {};
+
+ /**
+ * 权限码数组 ,int类型
+ * @return .
+ */
+ int [] valueInt() default {};
+
+ /**
+ * 权限码数组 ,long类型
+ * @return .
+ */
+ long [] valueLong() default {};
+
+ /**
+ * 是否属于and型验证 ,true=必须全部具有,false=只要具有一个就可以通过
+ * @return .
+ */
+ boolean isAnd() default true;
+
+}
diff --git a/sa-token-doc/doc/README.md b/sa-token-doc/doc/README.md
index de50ae43..bf5e8c27 100644
--- a/sa-token-doc/doc/README.md
+++ b/sa-token-doc/doc/README.md
@@ -19,6 +19,7 @@
- 持久层扩展(集成redis)
- 多账号认证体系(比如一个商城项目的user表和admin表)
- 无cookie模式(APP、小程序等前后台分离场景)
+- 注解式鉴权(优雅的将鉴权与业务代码分离)
- 零配置与Spring等框架集成
- ...
diff --git a/sa-token-doc/doc/_sidebar.md b/sa-token-doc/doc/_sidebar.md
index b79b83e3..a592e505 100644
--- a/sa-token-doc/doc/_sidebar.md
+++ b/sa-token-doc/doc/_sidebar.md
@@ -14,6 +14,7 @@
- [无cookie模式](/use/not-cookie)
- [模拟他人](/use/mock-person)
- [多账号验证](/use/many-account)
+ - [注解式鉴权](/use/at-check)
- [框架配置](/use/config)
- **其它**
diff --git a/sa-token-doc/doc/index.html b/sa-token-doc/doc/index.html
index f90bd305..1f5fd244 100644
--- a/sa-token-doc/doc/index.html
+++ b/sa-token-doc/doc/index.html
@@ -7,7 +7,7 @@
-
+