Compare commits
119 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ee16e919fe | |||
| 670cd4ae98 | |||
| 4f84818100 | |||
| 9398f07cb5 | |||
| 8826565f6a | |||
| e076c71648 | |||
| f5307a2eb0 | |||
| da22832ccf | |||
| 6977d3d136 | |||
| 0f7e1e977c | |||
| e918f613b8 | |||
| 106a710dd8 | |||
| 4607f51d1a | |||
| 954efeb732 | |||
| 8db78e0a5d | |||
| e5fb308628 | |||
| f2416a6175 | |||
| 591ad6ac53 | |||
| c0587d5e92 | |||
| 33ece1a2b0 | |||
| 1fcda76ce4 | |||
| e32979a7a6 | |||
| 6da234d285 | |||
| 5ec6c42671 | |||
| cd14651dcc | |||
| 686cef5a8e | |||
| cf58444bf0 | |||
| 2cfb8df28a | |||
| 83268da0cb | |||
| ac2d65042c | |||
| 6dfa750821 | |||
| e76169864d | |||
| fcf3cc43f4 | |||
| 56cb20aff6 | |||
| c09f5ae20e | |||
| e74a589b88 | |||
| 31b410eadd | |||
| 5c2d6076c9 | |||
| d1d5716ddc | |||
| 8506f234aa | |||
| 5120cfa1bb | |||
| 4c35f9e936 | |||
| d59b27cc66 | |||
| 13ff5c8306 | |||
| 195697c2b3 | |||
| 759dfc79cc | |||
| 35b37b0aea | |||
| 4c65c0be08 | |||
| 180fe0791b | |||
| b42deb823b | |||
| 60cdb12c69 | |||
| 871422044b | |||
| 7db7880f09 | |||
| aadad9bfa3 | |||
| 480c74d131 | |||
| b867787b0e | |||
| d901a45552 | |||
| 6f8a3a4249 | |||
| f5586a94ea | |||
| 1f84ea6939 | |||
| 0d69bde2ba | |||
| 2ef8a82614 | |||
| 05e8e8d130 | |||
| e30f4df048 | |||
| 45fcfc5e8e | |||
| 8c3477b48f | |||
| 45a77612ef | |||
| 296704c7c5 | |||
| 42d1872553 | |||
| f162834ded | |||
| 7278467411 | |||
| 5e9f58935c | |||
| dd8c55ed3c | |||
| 270ec74f84 | |||
| ffc487f7cb | |||
| 083164617c | |||
| 11664157a4 | |||
| b896173d5f | |||
| 17fa35e251 | |||
| 6566f60410 | |||
| 4a57a8ebdc | |||
| b3b89ebf53 | |||
| 62f92e9097 | |||
| 559fba69b8 | |||
| a19fadbd54 | |||
| 18d360799e | |||
| d3911deec7 | |||
| 1a1d90787a | |||
| fa3297d5f9 | |||
| b0e4864782 | |||
| 3193727486 | |||
| d2266d6967 | |||
| 172351ad04 | |||
| a1a67ca606 | |||
| 26c312f8d6 | |||
| 9b009d0d79 | |||
| f023326556 | |||
| 3b9b2f8791 | |||
| deb778ed41 | |||
| 3d49ce7092 | |||
| 705101256a | |||
| 289d9c966c | |||
| 186d8c6c8c | |||
| 0f875ae9e5 | |||
| a799b4cc49 | |||
| d006cf806d | |||
| 1add5403e8 | |||
| 09d3acf775 | |||
| d5c8108996 | |||
| f832c63a8c | |||
| 072a76132a | |||
| 1d1aed3719 | |||
| b16d033734 | |||
| 78238641a3 | |||
| b49c5f9a5f | |||
| e01b98e55a | |||
| 4555c48df9 | |||
| d8dc6f51cf | |||
| 1f5798176d |
@@ -13,4 +13,6 @@ unpackage/
|
||||
|
||||
.idea/
|
||||
|
||||
sa-token-three-plugin/
|
||||
|
||||
.flattened-pom.xml
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<p align="center">
|
||||
<img alt="logo" src="https://sa-token.cc/logo.png" width="150" height="150">
|
||||
</p>
|
||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">Sa-Token v1.35.0.RC</h1>
|
||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">Sa-Token v1.37.0</h1>
|
||||
<h4 align="center">一个轻量级 Java 权限认证框架,让鉴权变得简单、优雅!</h4>
|
||||
<p align="center">
|
||||
<a href="https://gitee.com/dromara/sa-token/stargazers"><img src="https://gitee.com/dromara/sa-token/badge/star.svg?theme=gvp"></a>
|
||||
@@ -18,9 +18,9 @@
|
||||
## 前言:
|
||||
- [在线文档:https://sa-token.cc](https://sa-token.cc)
|
||||
|
||||
- 注:学习测试请拉取 master 分支,dev 为正在开发的分支,有很多特性并不稳定。
|
||||
- 注:学习测试请拉取 master 分支,dev 是开发分支,有很多特性并不稳定(在项目根目录执行 `git checkout master`)。
|
||||
|
||||
- 开源不易,点个 star 鼓励一下吧!
|
||||
- 开源不易,点个 star 鼓励一下吧!
|
||||
|
||||
|
||||
## Sa-Token 介绍
|
||||
@@ -150,9 +150,9 @@ Sa-OAuth2 模块分为四种授权模式,解决不同场景下的授权需求
|
||||
|
||||
- [[ Snowy ]](https://gitee.com/xiaonuobase/snowy):国内首个国密前后分离快速开发平台,采用 Vue3 + AntDesignVue3 + Vite + SpringBoot + Mp + HuTool + SaToken。
|
||||
|
||||
- [[ RuoYi-Vue-Plus ]](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus):重写RuoYi-Vue所有功能 集成 Sa-Token+Mybatis-Plus+Jackson+Xxl-Job+knife4j+Hutool+OSS 定期同步
|
||||
- [[ RuoYi-Vue-Plus ]](https://gitee.com/dromara/RuoYi-Vue-Plus):重写RuoYi-Vue所有功能 集成 Sa-Token+Mybatis-Plus+Jackson+Xxl-Job+knife4j+Hutool+OSS 定期同步
|
||||
|
||||
- [[ RuoYi-Cloud-Plus ]](https://gitee.com/JavaLionLi/RuoYi-Cloud-Plus):重写RuoYi-Cloud所有功能 整合 SpringCloudAlibaba Dubbo3.0 Sa-Token Mybatis-Plus MQ OSS ES Xxl-Job Docker 全方位升级 定期同步
|
||||
- [[ RuoYi-Cloud-Plus ]](https://gitee.com/dromara/RuoYi-Cloud-Plus):重写RuoYi-Cloud所有功能 整合 SpringCloudAlibaba Dubbo3.0 Sa-Token Mybatis-Plus MQ OSS ES Xxl-Job Docker 全方位升级 定期同步
|
||||
|
||||
- [[ EasyAdmin ]](https://gitee.com/lakernote/easy-admin):一个基于SpringBoot2 + Sa-Token + Mybatis-Plus + Snakerflow + Layui 的后台管理系统,灵活多变可前后端分离,也可单体,内置代码生成器、权限管理、工作流引擎等
|
||||
|
||||
@@ -174,17 +174,22 @@ Sa-OAuth2 模块分为四种授权模式,解决不同场景下的授权需求
|
||||
|
||||
- [[ hippo4j ]](https://gitee.com/agentart/hippo4j):强大的动态线程池框架,附带监控报警功能。
|
||||
|
||||
- [[ hertzbeat ]](https://gitee.com/dromara/hertzbeat):易用友好的开源实时监控告警系统,无需Agent,高性能集群,强大自定义监控能力。
|
||||
|
||||
- [[ Solon ]](https://gitee.com/noear/solon):一个更现代感的应用开发框架:更快、更小、更自由。
|
||||
|
||||
|
||||
## 知识星球
|
||||
<img src="https://oss.dev33.cn/sa-token/dromara-xingqiu--sa-token.jpg" width="300px" />
|
||||
|
||||
|
||||
## 交流群
|
||||
QQ交流群:707350988 [点击加入](https://jq.qq.com/?_wv=1027&k=tqbzHT2D)
|
||||
QQ交流群:837325627 [点击加入](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=98NOhX0Q3a2hcv3eURcnYMBuZUZrlHUH&authKey=td3pmX3BnYNr%2FCRkEDwE5FgGARk29D9HAMwL0bAfK7tqN8XN93jccnEanyZl18mM&noverify=0&group_code=837325627)
|
||||
|
||||
微信交流群:
|
||||
|
||||

|
||||
<img src="https://oss.dev33.cn/sa-token/qr/wx-qr-m-400k.png" width="230px" title="微信群" />
|
||||
<!--  -->
|
||||
|
||||
(扫码添加微信,备注:sa-token,邀您加入群聊)
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
<!-- 一些属性 -->
|
||||
<properties>
|
||||
<revision>1.35.0.RC</revision>
|
||||
<revision>1.37.0</revision>
|
||||
<jdk.version>1.8</jdk.version>
|
||||
<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>utf-8</project.reporting.outputEncoding>
|
||||
|
||||
+12
-2
@@ -13,7 +13,7 @@
|
||||
<url>https://github.com/dromara/sa-token</url>
|
||||
|
||||
<properties>
|
||||
<revision>1.35.0.RC</revision>
|
||||
<revision>1.37.0</revision>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
@@ -46,6 +46,11 @@
|
||||
<artifactId>sa-token-reactor-spring-boot-starter</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-reactor-spring-boot3-starter</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-servlet</artifactId>
|
||||
@@ -124,6 +129,11 @@
|
||||
<artifactId>sa-token-redisson-jackson</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-redisson-jackson2</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-redisx</artifactId>
|
||||
@@ -249,4 +259,4 @@
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
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>
|
||||
|
||||
@@ -102,10 +102,13 @@ public class SaManager {
|
||||
SaTokenEventCenter.doRegisterComponent("SaTokenDao", saTokenDao);
|
||||
}
|
||||
private static void setSaTokenDaoMethod(SaTokenDao saTokenDao) {
|
||||
if((SaManager.saTokenDao instanceof SaTokenDaoDefaultImpl)) {
|
||||
((SaTokenDaoDefaultImpl)SaManager.saTokenDao).endRefreshThread();
|
||||
if (SaManager.saTokenDao != null) {
|
||||
SaManager.saTokenDao.destroy();
|
||||
}
|
||||
SaManager.saTokenDao = saTokenDao;
|
||||
if (SaManager.saTokenDao != null) {
|
||||
SaManager.saTokenDao.init();
|
||||
}
|
||||
}
|
||||
public static SaTokenDao getSaTokenDao() {
|
||||
if (saTokenDao == null) {
|
||||
|
||||
@@ -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.application;
|
||||
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
|
||||
/**
|
||||
* 应用全局信息
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.31.0
|
||||
*/
|
||||
public class ApplicationInfo {
|
||||
|
||||
/**
|
||||
* 应用前缀
|
||||
*/
|
||||
public static String routePrefix;
|
||||
|
||||
/**
|
||||
* 为指定 path 裁剪掉 routePrefix 前缀
|
||||
* @param path 指定 path
|
||||
* @return /
|
||||
*/
|
||||
public static String cutPathPrefix(String path) {
|
||||
if(! SaFoxUtil.isEmpty(routePrefix) && ! routePrefix.equals("/") && path.startsWith(routePrefix)){
|
||||
path = path.substring(routePrefix.length());
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -199,6 +199,20 @@ public interface SaTokenDao {
|
||||
* @return 查询到的数据集合
|
||||
*/
|
||||
List<String> searchData(String prefix, String keyword, int start, int size, boolean sortType);
|
||||
|
||||
|
||||
|
||||
|
||||
// --------------------- 生命周期 ---------------------
|
||||
|
||||
/**
|
||||
* 当此 SaTokenDao 实例被装载时触发
|
||||
*/
|
||||
default void init() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 当此 SaTokenDao 实例被卸载时触发
|
||||
*/
|
||||
default void destroy() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -40,14 +40,6 @@ public class SaTokenDaoDefaultImpl implements SaTokenDao {
|
||||
* 存储数据过期时间的集合(单位: 毫秒), 记录所有 key 的到期时间 (注意存储的是到期时间,不是剩余存活时间)
|
||||
*/
|
||||
public Map<String, Long> expireMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public SaTokenDaoDefaultImpl() {
|
||||
initRefreshThread();
|
||||
}
|
||||
|
||||
|
||||
// ------------------------ String 读写操作
|
||||
|
||||
@@ -260,12 +252,21 @@ public class SaTokenDaoDefaultImpl implements SaTokenDao {
|
||||
});
|
||||
this.refreshThread.start();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 结束定时任务,不再定时清理过期数据
|
||||
* 组件被安装时,开始刷新数据线程
|
||||
*/
|
||||
public void endRefreshThread() {
|
||||
this.refreshFlag = false;
|
||||
@Override
|
||||
public void init() {
|
||||
initRefreshThread();
|
||||
}
|
||||
|
||||
/**
|
||||
* 组件被卸载时,结束定时任务,不再定时清理过期数据
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
this.refreshFlag = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +154,12 @@ public interface SaErrorCode {
|
||||
/** sha256 加密异常 */
|
||||
int CODE_12113 = 12113;
|
||||
|
||||
/** sha384 加密异常 */
|
||||
int CODE_121131 = 121131;
|
||||
|
||||
/** sha512 加密异常 */
|
||||
int CODE_121132 = 121132;
|
||||
|
||||
/** AES 加密异常 */
|
||||
int CODE_12114 = 12114;
|
||||
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.exception;
|
||||
|
||||
/**
|
||||
* 一个异常:代表请求 path 无效或非法
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.37.0
|
||||
*/
|
||||
public class RequestPathInvalidException extends SaTokenException {
|
||||
|
||||
/**
|
||||
* 序列化版本号
|
||||
*/
|
||||
private static final long serialVersionUID = 8243974276159004739L;
|
||||
|
||||
/** 具体无效的 path */
|
||||
private final String path;
|
||||
|
||||
/**
|
||||
* @return 具体无效的 path
|
||||
*/
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public RequestPathInvalidException(String message, String path) {
|
||||
super(message);
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.fun.strategy;
|
||||
|
||||
import cn.dev33.satoken.exception.RequestPathInvalidException;
|
||||
|
||||
/**
|
||||
* 函数式接口:校验请求 path 的算法
|
||||
*
|
||||
* <p> 如果属于无效请求 path,则抛出异常 RequestPathInvalidException </p>
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.37.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface SaCheckRequestPathFunction {
|
||||
|
||||
/**
|
||||
* 执行函数
|
||||
* @param path 请求 path
|
||||
* @param extArg1 扩展参数1
|
||||
* @param extArg2 扩展参数2
|
||||
*/
|
||||
void run(String path, Object extArg1, Object extArg2);
|
||||
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.fun.strategy;
|
||||
|
||||
import cn.dev33.satoken.exception.RequestPathInvalidException;
|
||||
|
||||
/**
|
||||
* 函数式接口:当请求 path 校验不通过时处理方案的算法
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.37.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface SaRequestPathInvalidHandleFunction {
|
||||
|
||||
/**
|
||||
* 执行函数
|
||||
* @param e 请求 path 无效的异常对象
|
||||
* @param extArg1 扩展参数1
|
||||
* @param extArg2 扩展参数2
|
||||
*/
|
||||
void run(RequestPathInvalidException e, Object extArg1, Object extArg2);
|
||||
|
||||
}
|
||||
@@ -91,20 +91,8 @@ public class SaSecureUtil {
|
||||
public static String sha1(String str) {
|
||||
try {
|
||||
str = (str == null ? "" : str);
|
||||
MessageDigest md = MessageDigest.getInstance("SHA1");
|
||||
byte[] b = str.getBytes();
|
||||
md.update(b);
|
||||
byte[] b2 = md.digest();
|
||||
int len = b2.length;
|
||||
String strA = "0123456789abcdef";
|
||||
char[] ch = strA.toCharArray();
|
||||
char[] chs = new char[len * 2];
|
||||
for (int i = 0, k = 0; i < len; i++) {
|
||||
byte b3 = b2[i];
|
||||
chs[k++] = ch[b3 >>> 4 & 0xf];
|
||||
chs[k++] = ch[b3 & 0xf];
|
||||
}
|
||||
return new String(chs);
|
||||
MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
|
||||
return getShaHexString(str, messageDigest);
|
||||
} catch (Exception e) {
|
||||
throw new SaTokenException(e).setCode(SaErrorCode.CODE_12112);
|
||||
}
|
||||
@@ -120,25 +108,67 @@ public class SaSecureUtil {
|
||||
try {
|
||||
str = (str == null ? "" : str);
|
||||
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
|
||||
messageDigest.update(str.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
byte[] bytes = messageDigest.digest();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
String temp;
|
||||
for (byte aByte : bytes) {
|
||||
temp = Integer.toHexString(aByte & 0xFF);
|
||||
if (temp.length() == 1) {
|
||||
builder.append("0");
|
||||
}
|
||||
builder.append(temp);
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
return getShaHexString(str, messageDigest);
|
||||
} catch (Exception e) {
|
||||
throw new SaTokenException(e).setCode(SaErrorCode.CODE_12113);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sha384加密
|
||||
*
|
||||
* @param str 指定字符串
|
||||
* @return 加密后的字符串
|
||||
*/
|
||||
public static String sha384(String str) {
|
||||
try {
|
||||
str = (str == null ? "" : str);
|
||||
MessageDigest messageDigest = MessageDigest.getInstance("SHA-384");
|
||||
return getShaHexString(str, messageDigest);
|
||||
} catch (Exception e) {
|
||||
throw new SaTokenException(e).setCode(SaErrorCode.CODE_121131);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sha512加密
|
||||
*
|
||||
* @param str 指定字符串
|
||||
* @return 加密后的字符串
|
||||
*/
|
||||
public static String sha512(String str) {
|
||||
try {
|
||||
str = (str == null ? "" : str);
|
||||
MessageDigest messageDigest = MessageDigest.getInstance("SHA-512");
|
||||
return getShaHexString(str, messageDigest);
|
||||
} catch (Exception e) {
|
||||
throw new SaTokenException(e).setCode(SaErrorCode.CODE_121132);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sha (Secure Hash Algorithm)加密 公共方法
|
||||
*
|
||||
* @param str 指定字符串
|
||||
* @param messageDigest 消息摘要
|
||||
* @return 加密后的字符串
|
||||
*/
|
||||
private static String getShaHexString(String str, MessageDigest messageDigest) {
|
||||
messageDigest.update(str.getBytes(StandardCharsets.UTF_8));
|
||||
byte[] bytes = messageDigest.digest();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
String temp;
|
||||
for (byte aByte : bytes) {
|
||||
temp = Integer.toHexString(aByte & 0xFF); // 获取无符号整数十六进制字符串
|
||||
if (temp.length() == 1) {
|
||||
builder.append("0"); // 确保每个字节都用两个字符表示
|
||||
}
|
||||
builder.append(temp);
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* md5加盐加密: md5(md5(str) + md5(salt))
|
||||
* @param str 字符串
|
||||
@@ -149,6 +179,15 @@ public class SaSecureUtil {
|
||||
return md5(md5(str) + md5(salt));
|
||||
}
|
||||
|
||||
/**
|
||||
* sha256加盐加密: sha256(sha256(str) + sha256(salt))
|
||||
* @param str 字符串
|
||||
* @param salt 盐
|
||||
* @return 加密后的字符串
|
||||
*/
|
||||
public static String sha256BySalt(String str, String salt) {
|
||||
return sha256(sha256(str) + sha256(salt));
|
||||
}
|
||||
|
||||
// ----------------------- 对称加密 AES -----------------------
|
||||
|
||||
|
||||
@@ -294,9 +294,9 @@ public class SaSignTemplate {
|
||||
String nonceValue = paramMap.get(nonce);
|
||||
String signValue = paramMap.get(sign);
|
||||
|
||||
// 三个参数必须全部非空
|
||||
// 参数非空校验
|
||||
SaSignException.throwByNull(timestampValue, "缺少 timestamp 字段");
|
||||
SaSignException.throwByNull(nonceValue, "缺少 nonce 字段");
|
||||
// SaSignException.throwByNull(nonceValue, "缺少 nonce 字段"); // 配置isCheckNonce=false时,可以不传 nonce
|
||||
SaSignException.throwByNull(signValue, "缺少 sign 字段");
|
||||
|
||||
// 三个值的校验必须全部通过
|
||||
@@ -315,6 +315,11 @@ public class SaSignTemplate {
|
||||
String nonceValue = paramMap.get(nonce);
|
||||
String signValue = paramMap.get(sign);
|
||||
|
||||
// 参数非空校验
|
||||
SaSignException.throwByNull(timestampValue, "缺少 timestamp 字段");
|
||||
// SaSignException.throwByNull(nonceValue, "缺少 nonce 字段"); // 配置isCheckNonce=false时,可以不传 nonce
|
||||
SaSignException.throwByNull(signValue, "缺少 sign 字段");
|
||||
|
||||
// 依次校验三个参数
|
||||
checkTimestamp(Long.parseLong(timestampValue));
|
||||
if(getSignConfigOrGlobal().getIsCheckNonce()) {
|
||||
|
||||
@@ -569,7 +569,7 @@ public class StpLogic {
|
||||
throw new SaTokenException("loginId 不能为以下值:" + NotLoginException.ABNORMAL_LIST);
|
||||
}
|
||||
|
||||
// 3、账号 id 不能是简单类型
|
||||
// 3、账号 id 不能是复杂类型
|
||||
if( ! SaFoxUtil.isBasicType(id.getClass())) {
|
||||
SaManager.log.warn("loginId 应该为简单类型,例如:String | int | long,不推荐使用复杂类型:" + id.getClass());
|
||||
}
|
||||
@@ -994,9 +994,11 @@ public class StpLogic {
|
||||
if(loginId == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
// 3、不为 null,则开始尝试类型转换
|
||||
return (T)SaFoxUtil.getValueByType(loginId, defaultValue.getClass());
|
||||
// 3、loginId 不为 null,则开始尝试类型转换
|
||||
if (defaultValue == null) {
|
||||
return null;
|
||||
}
|
||||
return (T) SaFoxUtil.getValueByType(loginId, defaultValue.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1173,6 +1175,11 @@ public class StpLogic {
|
||||
*/
|
||||
public SaSession getSessionBySessionId(String sessionId, boolean isCreate, Consumer<SaSession> appendOperation) {
|
||||
|
||||
// 如果提供的 sessionId 为 null,则直接返回 null
|
||||
if(SaFoxUtil.isEmpty(sessionId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 先检查这个 SaSession 是否已经存在,如果不存在且 isCreate=true,则新建并返回
|
||||
SaSession session = getSaTokenDao().getSession(sessionId);
|
||||
|
||||
@@ -1723,11 +1730,7 @@ public class StpLogic {
|
||||
* @return /
|
||||
*/
|
||||
public List<String> getRoleList() {
|
||||
try {
|
||||
return getRoleList(getLoginId());
|
||||
} catch (NotLoginException e) {
|
||||
return SaFoxUtil.emptyList();
|
||||
}
|
||||
return getRoleList(getLoginId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1771,7 +1774,7 @@ public class StpLogic {
|
||||
try {
|
||||
checkRoleAnd(roleArray);
|
||||
return true;
|
||||
} catch (NotLoginException | NotRoleException e) {
|
||||
} catch (NotRoleException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1786,7 +1789,7 @@ public class StpLogic {
|
||||
try {
|
||||
checkRoleOr(roleArray);
|
||||
return true;
|
||||
} catch (NotLoginException | NotRoleException e) {
|
||||
} catch (NotRoleException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1861,11 +1864,7 @@ public class StpLogic {
|
||||
* @return /
|
||||
*/
|
||||
public List<String> getPermissionList() {
|
||||
try {
|
||||
return getPermissionList(getLoginId());
|
||||
} catch (NotLoginException e) {
|
||||
return SaFoxUtil.emptyList();
|
||||
}
|
||||
return getPermissionList(getLoginId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1909,7 +1908,7 @@ public class StpLogic {
|
||||
try {
|
||||
checkPermissionAnd(permissionArray);
|
||||
return true;
|
||||
} catch (NotLoginException | NotPermissionException e) {
|
||||
} catch (NotPermissionException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1924,7 +1923,7 @@ public class StpLogic {
|
||||
try {
|
||||
checkPermissionOr(permissionArray);
|
||||
return true;
|
||||
} catch (NotLoginException | NotPermissionException e) {
|
||||
} catch (NotPermissionException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package cn.dev33.satoken.strategy;
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.annotation.*;
|
||||
import cn.dev33.satoken.basic.SaBasicUtil;
|
||||
import cn.dev33.satoken.exception.RequestPathInvalidException;
|
||||
import cn.dev33.satoken.exception.SaTokenException;
|
||||
import cn.dev33.satoken.fun.strategy.*;
|
||||
import cn.dev33.satoken.session.SaSession;
|
||||
@@ -329,6 +330,49 @@ public final class SaStrategy {
|
||||
return new StpLogic(loginType);
|
||||
};
|
||||
|
||||
/**
|
||||
* 请求 path 不允许出现的字符
|
||||
*/
|
||||
public static String[] INVALID_CHARACTER = {
|
||||
"//", "\\",
|
||||
"%2e", "%2E", // .
|
||||
"%2f", "%2F", // /
|
||||
"%5c", "%5C", // \
|
||||
"%25" // 空格
|
||||
};
|
||||
|
||||
/**
|
||||
* 校验请求 path 的算法
|
||||
*/
|
||||
public SaCheckRequestPathFunction checkRequestPath = (requestPath, extArg1, extArg2) -> {
|
||||
|
||||
// 不允许为null
|
||||
if(requestPath == null) {
|
||||
throw new RequestPathInvalidException("非法请求:null", null);
|
||||
}
|
||||
// 不允许包含非法字符
|
||||
for (String item : INVALID_CHARACTER) {
|
||||
if (requestPath.contains(item)) {
|
||||
throw new RequestPathInvalidException("非法请求:" + requestPath, requestPath);
|
||||
}
|
||||
}
|
||||
// 不允许出现跨目录
|
||||
if(requestPath.contains("/.") || requestPath.contains("\\.")) {
|
||||
throw new RequestPathInvalidException("非法请求:" + requestPath, requestPath);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 当请求 path 校验不通过时处理方案的算法,自定义示例:
|
||||
* <pre>
|
||||
* SaStrategy.instance.requestPathInvalidHandle = (e, extArg1, extArg2) -> {
|
||||
* // 自定义处理逻辑 ...
|
||||
* };
|
||||
* </pre>
|
||||
*/
|
||||
public SaRequestPathInvalidHandleFunction requestPathInvalidHandle = null;
|
||||
|
||||
|
||||
// ----------------------- 重写策略 set连缀风格
|
||||
|
||||
|
||||
@@ -251,8 +251,39 @@ public class SaFoxUtil {
|
||||
if( ! patt.contains("*")) {
|
||||
return patt.equals(str);
|
||||
}
|
||||
// 正则匹配
|
||||
return Pattern.matches(patt.replaceAll("\\*", ".*"), str);
|
||||
// 深入匹配
|
||||
return vagueMatchMethod(patt, str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串模糊匹配
|
||||
*
|
||||
* @param pattern /
|
||||
* @param str /
|
||||
* @return /
|
||||
*/
|
||||
private static boolean vagueMatchMethod( String pattern, String str) {
|
||||
int m = str.length();
|
||||
int n = pattern.length();
|
||||
boolean[][] dp = new boolean[m + 1][n + 1];
|
||||
dp[0][0] = true;
|
||||
for (int i = 1; i <= n; ++i) {
|
||||
if (pattern.charAt(i - 1) == '*') {
|
||||
dp[0][i] = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = 1; i <= m; ++i) {
|
||||
for (int j = 1; j <= n; ++j) {
|
||||
if (pattern.charAt(j - 1) == '*') {
|
||||
dp[i][j] = dp[i][j - 1] || dp[i - 1][j];
|
||||
} else if (str.charAt(i - 1) == pattern.charAt(j - 1)) {
|
||||
dp[i][j] = dp[i - 1][j - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp[m][n];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -36,7 +36,7 @@ public class SaTokenConsts {
|
||||
/**
|
||||
* Sa-Token 当前版本号
|
||||
*/
|
||||
public static final String VERSION_NO = "v1.35.0.RC";
|
||||
public static final String VERSION_NO = "v1.37.0";
|
||||
|
||||
/**
|
||||
* Sa-Token 开源地址 Gitee
|
||||
@@ -186,6 +186,28 @@ public class SaTokenConsts {
|
||||
*/
|
||||
public static final int ASSEMBLY_ORDER = -100;
|
||||
|
||||
/**
|
||||
* 请求 path 校验过滤器的注册顺序
|
||||
*/
|
||||
public static final int PATH_CHECK_FILTER_ORDER = -1000;
|
||||
|
||||
/**
|
||||
* Content-Type key
|
||||
*/
|
||||
public static final String CONTENT_TYPE_KEY = "Content-Type";
|
||||
|
||||
/**
|
||||
* Content-Type text/plain; charset=utf-8
|
||||
*/
|
||||
public static final String CONTENT_TYPE_TEXT_PLAIN = "text/plain; charset=utf-8";
|
||||
|
||||
/**
|
||||
* Content-Type application/json;charset=UTF-8
|
||||
*/
|
||||
public static final String CONTENT_TYPE_APPLICATION_JSON = "application/json;charset=UTF-8";
|
||||
|
||||
|
||||
|
||||
|
||||
// =================== 废弃 ===================
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -73,7 +73,7 @@
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-bom</artifactId>
|
||||
<version>1.35.0</version>
|
||||
<version>1.37.0</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
<java.run.main.class>com.pj.SaTokenCrossCookieApplication</java.run.main.class>
|
||||
</properties>
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
<java.run.main.class>com.pj.SaTokenCrossHeaderApplication</java.run.main.class>
|
||||
</properties>
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
<dubbo.version>2.7.21</dubbo.version>
|
||||
<nacos.version>1.4.2</nacos.version>
|
||||
</properties>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
<dubbo.version>2.7.21</dubbo.version>
|
||||
<nacos.version>1.4.2</nacos.version>
|
||||
</properties>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
<dubbo.version>3.2.2</dubbo.version>
|
||||
<nacos.version>2.2.2</nacos.version>
|
||||
</properties>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
<dubbo.version>3.2.2</dubbo.version>
|
||||
<nacos.version>2.2.2</nacos.version>
|
||||
</properties>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<lombok.version>1.18.10</lombok.version>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<java.version>1.8</java.version>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<java.version>1.8</java.version>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
<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/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-demo-solon-redisson</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
|
||||
<!-- Solon -->
|
||||
<parent>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon-parent</artifactId>
|
||||
<version>2.4.0</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Solon 依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon.logging.simple</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>redisson-solon-plugin</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Sa-Token 权限认证, 在线文档:https://sa-token.cc/ -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-solon-plugin</artifactId>
|
||||
<version>${sa-token.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- sa-token整合redis (使用jdk默认序列化方式) -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-redisson-jackson2</artifactId>
|
||||
<version>${sa-token.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- hutool工具类,用来生成雪花算法唯一id -->
|
||||
<!-- <dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.5.4</version>
|
||||
</dependency> -->
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<compilerArgument>-parameters</compilerArgument>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.pj;
|
||||
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import org.noear.solon.Solon;
|
||||
import org.noear.solon.annotation.SolonMain;
|
||||
|
||||
/**
|
||||
* sa-token整合 solon 示例
|
||||
* @author noear
|
||||
*
|
||||
*/
|
||||
@SolonMain
|
||||
public class SaTokenDemoApp {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Solon.start(SaTokenDemoApp.class, args);
|
||||
System.out.println("\n启动成功:Sa-Token配置如下:" + SaManager.getConfig());
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
package com.pj.satoken;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import cn.dev33.satoken.log.SaLog;
|
||||
import cn.dev33.satoken.log.SaLogForConsole;
|
||||
import cn.dev33.satoken.util.StrFormatter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* 将 Sa-Token log 信息转接到 slf4j 接口
|
||||
*
|
||||
* @author noear 2022/11/14 created
|
||||
*/
|
||||
//@Component
|
||||
public class SaLogForSlf4j extends SaLogForConsole implements SaLog {
|
||||
static final Logger log = LoggerFactory.getLogger(SaLogForSlf4j.class);
|
||||
|
||||
/**
|
||||
* 打印日志到控制台
|
||||
*
|
||||
* @param level 日志等级
|
||||
* @param str 字符串
|
||||
* @param args 参数列表
|
||||
*/
|
||||
public void println(int level, String str, Object... args) {
|
||||
SaTokenConfig config = SaManager.getConfig();
|
||||
|
||||
if (config.getIsLog() && level >= config.getLogLevelInt()) {
|
||||
switch (level) {
|
||||
case trace:
|
||||
log.trace(LOG_PREFIX + StrFormatter.format(str, args));
|
||||
break;
|
||||
case debug:
|
||||
log.debug(LOG_PREFIX + StrFormatter.format(str, args));
|
||||
break;
|
||||
case info:
|
||||
log.info(LOG_PREFIX + StrFormatter.format(str, args));
|
||||
break;
|
||||
case warn:
|
||||
log.warn(LOG_PREFIX + StrFormatter.format(str, args));
|
||||
break;
|
||||
case error:
|
||||
case fatal:
|
||||
log.error(LOG_PREFIX + StrFormatter.format(str, args));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
package com.pj.satoken;
|
||||
|
||||
import org.noear.solon.core.util.LogUtil;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import cn.dev33.satoken.log.SaLog;
|
||||
import cn.dev33.satoken.log.SaLogForConsole;
|
||||
import cn.dev33.satoken.util.StrFormatter;
|
||||
|
||||
/**
|
||||
* 将 Sa-Token log 信息转接到 Solon
|
||||
*
|
||||
* @author click33
|
||||
* @since 2022-11-2
|
||||
*/
|
||||
//@Component
|
||||
public class SaLogForSolon extends SaLogForConsole implements SaLog {
|
||||
|
||||
/**
|
||||
* 打印日志到控制台
|
||||
*
|
||||
* @param level 日志等级
|
||||
* @param str 字符串
|
||||
* @param args 参数列表
|
||||
*/
|
||||
public void println(int level, String str, Object... args) {
|
||||
SaTokenConfig config = SaManager.getConfig();
|
||||
|
||||
if (config.getIsLog() && level >= config.getLogLevelInt()) {
|
||||
switch (level) {
|
||||
case trace:
|
||||
LogUtil.global().trace(LOG_PREFIX + StrFormatter.format(str, args));
|
||||
break;
|
||||
case debug:
|
||||
LogUtil.global().debug(LOG_PREFIX + StrFormatter.format(str, args));
|
||||
break;
|
||||
case info:
|
||||
LogUtil.global().info(LOG_PREFIX + StrFormatter.format(str, args));
|
||||
break;
|
||||
case warn:
|
||||
LogUtil.global().warn(LOG_PREFIX + StrFormatter.format(str, args));
|
||||
break;
|
||||
case error:
|
||||
case fatal:
|
||||
LogUtil.global().error(LOG_PREFIX + StrFormatter.format(str, args));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
package com.pj.satoken;
|
||||
|
||||
|
||||
import cn.dev33.satoken.dao.SaTokenDao;
|
||||
import cn.dev33.satoken.dao.SaTokenDaoRedissonJackson;
|
||||
import cn.dev33.satoken.solon.integration.SaTokenInterceptor;
|
||||
import org.noear.solon.Solon;
|
||||
import org.noear.solon.annotation.Bean;
|
||||
import org.noear.solon.annotation.Configuration;
|
||||
|
||||
import com.pj.util.AjaxJson;
|
||||
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import org.noear.solon.annotation.Inject;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.redisson.solon.RedissonSupplier;
|
||||
|
||||
|
||||
/**
|
||||
* [Sa-Token 权限认证] 配置类
|
||||
* @author click33
|
||||
* @author noear
|
||||
*/
|
||||
@Configuration
|
||||
public class SaTokenConfigure {
|
||||
|
||||
/**
|
||||
* 注册 [sa-token全局过滤器]
|
||||
*/
|
||||
@Bean(index = -100)
|
||||
public SaTokenInterceptor tokenPathFilter() {
|
||||
return new SaTokenInterceptor()
|
||||
|
||||
// 指定 [拦截路由] 与 [放行路由]
|
||||
.addInclude("/**").addExclude("/favicon.ico")
|
||||
|
||||
// 认证函数: 每次请求执行
|
||||
.setAuth(r -> {
|
||||
// System.out.println("---------- sa全局认证");
|
||||
|
||||
// SaRouter.match("/test/test", () -> new Object());
|
||||
})
|
||||
|
||||
// 异常处理函数:每次认证函数发生异常时执行此函数
|
||||
.setError(e -> {
|
||||
System.out.println("---------- sa全局异常 ");
|
||||
return AjaxJson.getError(e.getMessage());
|
||||
})
|
||||
|
||||
// 前置函数:在每次认证函数之前执行(BeforeAuth 不受 includeList 与 excludeList 的限制,所有请求都会进入)
|
||||
.setBeforeAuth(r -> {
|
||||
// ---------- 设置一些安全响应头 ----------
|
||||
SaHolder.getResponse()
|
||||
// 服务器名称
|
||||
.setServer("sa-server")
|
||||
// 是否可以在iframe显示视图: DENY=不可以 | SAMEORIGIN=同域下可以 | ALLOW-FROM uri=指定域名下可以
|
||||
.setHeader("X-Frame-Options", "SAMEORIGIN")
|
||||
// 是否启用浏览器默认XSS防护: 0=禁用 | 1=启用 | 1; mode=block 启用, 并在检查到XSS攻击时,停止渲染页面
|
||||
.setHeader("X-Frame-Options", "1; mode=block")
|
||||
// 禁用浏览器内容嗅探
|
||||
.setHeader("X-Content-Type-Options", "nosniff")
|
||||
;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造 RedissonClient
|
||||
* */
|
||||
@Bean
|
||||
public RedissonClient saTokenDaoInit(@Inject("${sa-token-dao}") RedissonSupplier supplier) {
|
||||
return supplier.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 SaTokenDao
|
||||
* */
|
||||
@Bean
|
||||
public SaTokenDao saTokenDaoInit(RedissonClient redissonClient) {
|
||||
return new SaTokenDaoRedissonJackson(redissonClient);
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.pj.satoken;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
import cn.dev33.satoken.stp.StpInterface;
|
||||
import org.noear.solon.annotation.Component;
|
||||
|
||||
/**
|
||||
* 自定义权限验证接口扩展
|
||||
*/
|
||||
@Component // 打开此注解,保证此类被 solon 扫描,即可完成 sa-token 的自定义权限验证扩展
|
||||
public class StpInterfaceImpl implements StpInterface {
|
||||
|
||||
/**
|
||||
* 返回一个账号所拥有的权限码集合
|
||||
*/
|
||||
@Override
|
||||
public List<String> getPermissionList(Object loginId, String loginType) {
|
||||
// 本list仅做模拟,实际项目中要根据具体业务逻辑来查询权限
|
||||
List<String> list = new ArrayList<String>();
|
||||
list.add("101");
|
||||
list.add("user-add");
|
||||
list.add("user-delete");
|
||||
list.add("user-update");
|
||||
list.add("user-get");
|
||||
list.add("article-get");
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回一个账号所拥有的角色标识集合
|
||||
*/
|
||||
@Override
|
||||
public List<String> getRoleList(Object loginId, String loginType) {
|
||||
// 本list仅做模拟,实际项目中要根据具体业务逻辑来查询角色
|
||||
List<String> list = new ArrayList<String>();
|
||||
list.add("admin");
|
||||
list.add("super-admin");
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package com.pj.test;
|
||||
|
||||
import com.pj.util.AjaxJson;
|
||||
|
||||
import cn.dev33.satoken.exception.*;
|
||||
|
||||
import org.noear.solon.annotation.Component;
|
||||
import org.noear.solon.core.handle.Context;
|
||||
import org.noear.solon.core.handle.Filter;
|
||||
import org.noear.solon.core.handle.FilterChain;
|
||||
|
||||
|
||||
/**
|
||||
* 全局异常处理
|
||||
*
|
||||
* @author noear
|
||||
*/
|
||||
@Component
|
||||
public class GlobalExceptionFilter implements Filter {
|
||||
@Override
|
||||
public void doFilter(Context ctx, FilterChain chain) throws Throwable {
|
||||
try {
|
||||
chain.doFilter(ctx);
|
||||
} catch (SaTokenException e) {
|
||||
// 不同异常返回不同状态码
|
||||
AjaxJson aj = null;
|
||||
if (e instanceof NotLoginException) { // 如果是未登录异常
|
||||
NotLoginException ee = (NotLoginException) e;
|
||||
aj = AjaxJson.getNotLogin().setMsg(ee.getMessage());
|
||||
} else if (e instanceof NotRoleException) { // 如果是角色异常
|
||||
NotRoleException ee = (NotRoleException) e;
|
||||
aj = AjaxJson.getNotJur("无此角色:" + ee.getRole());
|
||||
} else if (e instanceof NotPermissionException) { // 如果是权限异常
|
||||
NotPermissionException ee = (NotPermissionException) e;
|
||||
aj = AjaxJson.getNotJur("无此权限:" + ee.getPermission());
|
||||
} else if (e instanceof DisableServiceException) { // 如果是被封禁异常
|
||||
DisableServiceException ee = (DisableServiceException) e;
|
||||
aj = AjaxJson.getNotJur("账号被封禁:" + ee.getDisableTime() + "秒后解封");
|
||||
} else { // 普通异常, 输出:500 + 异常信息
|
||||
aj = AjaxJson.getError(e.getMessage());
|
||||
}
|
||||
|
||||
ctx.render(aj);
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.pj.test;
|
||||
|
||||
import org.noear.solon.annotation.Controller;
|
||||
import org.noear.solon.annotation.Mapping;
|
||||
|
||||
import com.pj.util.AjaxJson;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import org.noear.solon.annotation.Param;
|
||||
|
||||
/**
|
||||
* 测试: 同域单点登录
|
||||
* @author click33
|
||||
* @author noear
|
||||
*/
|
||||
@Controller
|
||||
@Mapping("/sso/")
|
||||
public class SSOController {
|
||||
|
||||
// 测试:进行登录
|
||||
@Mapping("doLogin")
|
||||
public AjaxJson doLogin(@Param(defaultValue = "10001") String id) {
|
||||
System.out.println("---------------- 进行登录 ");
|
||||
StpUtil.login(id);
|
||||
return AjaxJson.getSuccess("登录成功: " + id);
|
||||
}
|
||||
|
||||
// 测试:是否登录
|
||||
@Mapping("isLogin")
|
||||
public AjaxJson isLogin() {
|
||||
System.out.println("---------------- 是否登录 ");
|
||||
boolean isLogin = StpUtil.isLogin();
|
||||
return AjaxJson.getSuccess("是否登录: " + isLogin);
|
||||
}
|
||||
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package com.pj.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.noear.solon.annotation.Controller;
|
||||
import org.noear.solon.annotation.Mapping;
|
||||
|
||||
import com.pj.util.AjaxJson;
|
||||
import com.pj.util.Ttime;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
|
||||
/**
|
||||
* 压力测试
|
||||
* @author click33
|
||||
* @author noear
|
||||
*/
|
||||
@Controller
|
||||
@Mapping("/s-test/")
|
||||
public class StressTestController {
|
||||
|
||||
|
||||
// 测试 浏览器访问: http://localhost:8081/s-test/login
|
||||
// 测试前,请先将 is-read-cookie 配置为 false
|
||||
@Mapping("login")
|
||||
public AjaxJson login() {
|
||||
// StpUtil.getTokenSession().logout();
|
||||
// StpUtil.logoutByLoginId(10001);
|
||||
|
||||
int count = 10; // 循环多少轮
|
||||
int loginCount = 10000; // 每轮循环多少次
|
||||
|
||||
// 循环10次 取平均时间
|
||||
List<Double> list = new ArrayList<>();
|
||||
for (int i = 1; i <= count; i++) {
|
||||
System.out.println("\n---------------------第" + i + "轮---------------------");
|
||||
Ttime t = new Ttime().start();
|
||||
// 每次登录的次数
|
||||
for (int j = 1; j <= loginCount; j++) {
|
||||
StpUtil.login("1000" + j, "PC-" + j);
|
||||
if(j % 1000 == 0) {
|
||||
System.out.println("已登录:" + j);
|
||||
}
|
||||
}
|
||||
t.end();
|
||||
list.add((t.returnMs() + 0.0) / 1000);
|
||||
System.out.println("第" + i + "轮" + "用时:" + t.toString());
|
||||
}
|
||||
// System.out.println(((SaTokenDaoDefaultImpl)SaTokenManager.getSaTokenDao()).dataMap.size());
|
||||
|
||||
System.out.println("\n---------------------测试结果---------------------");
|
||||
System.out.println(list.size() + "次测试: " + list);
|
||||
double ss = 0;
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
ss += list.get(i);
|
||||
}
|
||||
System.out.println("平均用时: " + ss / list.size());
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
}
|
||||
+252
@@ -0,0 +1,252 @@
|
||||
package com.pj.test;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.pj.util.AjaxJson;
|
||||
import com.pj.util.Ttime;
|
||||
|
||||
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.session.SaSessionCustomUtil;
|
||||
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import org.noear.snack.ONode;
|
||||
import org.noear.solon.annotation.Controller;
|
||||
import org.noear.solon.annotation.Mapping;
|
||||
import org.noear.solon.annotation.Param;
|
||||
|
||||
/**
|
||||
* 测试专用Controller
|
||||
* @author click33
|
||||
* @author noear
|
||||
*/
|
||||
@Controller
|
||||
@Mapping("/test/")
|
||||
public class TestController {
|
||||
|
||||
|
||||
// 测试登录接口, 浏览器访问: http://localhost:8081/test/login
|
||||
@Mapping("login")
|
||||
public AjaxJson login(@Param(defaultValue="10001") String id) {
|
||||
System.out.println("======================= 进入方法,测试登录接口 ========================= ");
|
||||
System.out.println("当前会话的token:" + StpUtil.getTokenValue());
|
||||
System.out.println("当前是否登录:" + StpUtil.isLogin());
|
||||
System.out.println("当前登录账号:" + StpUtil.getLoginIdDefaultNull());
|
||||
|
||||
StpUtil.login(id); // 在当前会话登录此账号
|
||||
System.out.println("登录成功");
|
||||
System.out.println("当前是否登录:" + StpUtil.isLogin());
|
||||
System.out.println("当前登录账号:" + StpUtil.getLoginId());
|
||||
// System.out.println("当前登录账号并转为int:" + StpUtil.getLoginIdAsInt());
|
||||
System.out.println("当前登录设备:" + StpUtil.getLoginDevice());
|
||||
// System.out.println("当前token信息:" + StpUtil.getTokenInfo());
|
||||
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
// 测试退出登录 , 浏览器访问: http://localhost:8081/test/logout
|
||||
@Mapping("logout")
|
||||
public AjaxJson logout() {
|
||||
StpUtil.logout();
|
||||
// StpUtil.logoutByLoginId(10001);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
// 测试角色接口, 浏览器访问: http://localhost:8081/test/testRole
|
||||
@Mapping("testRole")
|
||||
public AjaxJson testRole() {
|
||||
System.out.println("======================= 进入方法,测试角色接口 ========================= ");
|
||||
|
||||
System.out.println("是否具有角色标识 user " + StpUtil.hasRole("user"));
|
||||
System.out.println("是否具有角色标识 admin " + StpUtil.hasRole("admin"));
|
||||
|
||||
System.out.println("没有admin权限就抛出异常");
|
||||
StpUtil.checkRole("admin");
|
||||
|
||||
System.out.println("在【admin、user】中只要拥有一个就不会抛出异常");
|
||||
StpUtil.checkRoleOr("admin", "user");
|
||||
|
||||
System.out.println("在【admin、user】中必须全部拥有才不会抛出异常");
|
||||
StpUtil.checkRoleAnd("admin", "user");
|
||||
|
||||
System.out.println("角色测试通过");
|
||||
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
// 测试权限接口, 浏览器访问: http://localhost:8081/test/testJur
|
||||
@Mapping("testJur")
|
||||
public AjaxJson testJur() {
|
||||
System.out.println("======================= 进入方法,测试权限接口 ========================= ");
|
||||
|
||||
System.out.println("是否具有权限101" + StpUtil.hasPermission("101"));
|
||||
System.out.println("是否具有权限user-add" + StpUtil.hasPermission("user-add"));
|
||||
System.out.println("是否具有权限article-get" + StpUtil.hasPermission("article-get"));
|
||||
|
||||
System.out.println("没有user-add权限就抛出异常");
|
||||
StpUtil.checkPermission("user-add");
|
||||
|
||||
System.out.println("在【101、102】中只要拥有一个就不会抛出异常");
|
||||
StpUtil.checkPermissionOr("101", "102");
|
||||
|
||||
System.out.println("在【101、102】中必须全部拥有才不会抛出异常");
|
||||
StpUtil.checkPermissionAnd("101", "102");
|
||||
|
||||
System.out.println("权限测试通过");
|
||||
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
// 测试会话session接口, 浏览器访问: http://localhost:8081/test/session
|
||||
@Mapping("session")
|
||||
public AjaxJson session() {
|
||||
System.out.println("======================= 进入方法,测试会话session接口 ========================= ");
|
||||
System.out.println("当前是否登录:" + StpUtil.isLogin());
|
||||
System.out.println("当前登录账号session的id" + StpUtil.getSession().getId());
|
||||
System.out.println("当前登录账号session的id" + StpUtil.getSession().getId());
|
||||
System.out.println("测试取值name:" + StpUtil.getSession().get("name"));
|
||||
StpUtil.getSession().set("name", new Date()); // 写入一个值
|
||||
System.out.println("测试取值name:" + StpUtil.getSession().get("name"));
|
||||
System.out.println( ONode.stringify(StpUtil.getSession()));
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
// 测试自定义session接口, 浏览器访问: http://localhost:8081/test/session2
|
||||
@Mapping("session2")
|
||||
public AjaxJson session2() {
|
||||
System.out.println("======================= 进入方法,测试自定义session接口 ========================= ");
|
||||
// 自定义session就是无需登录也可以使用 的session :比如拿用户的手机号当做 key, 来获取 session
|
||||
System.out.println("自定义 session的id为:" + SaSessionCustomUtil.getSessionById("1895544896").getId());
|
||||
System.out.println("测试取值name:" + SaSessionCustomUtil.getSessionById("1895544896").get("name"));
|
||||
SaSessionCustomUtil.getSessionById("1895544896").set("name", "张三"); // 写入值
|
||||
System.out.println("测试取值name:" + SaSessionCustomUtil.getSessionById("1895544896").get("name"));
|
||||
System.out.println("测试取值name:" + SaSessionCustomUtil.getSessionById("1895544896").get("name"));
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
// ----------
|
||||
// 测试token专属session, 浏览器访问: http://localhost:8081/test/getTokenSession
|
||||
@Mapping("getTokenSession")
|
||||
public AjaxJson getTokenSession() {
|
||||
System.out.println("======================= 进入方法,测试会话session接口 ========================= ");
|
||||
System.out.println("当前是否登录:" + StpUtil.isLogin());
|
||||
System.out.println("当前token专属session: " + StpUtil.getTokenSession().getId());
|
||||
|
||||
System.out.println("测试取值name:" + StpUtil.getTokenSession().get("name"));
|
||||
StpUtil.getTokenSession().set("name", "张三"); // 写入一个值
|
||||
System.out.println("测试取值name:" + StpUtil.getTokenSession().get("name"));
|
||||
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
// 打印当前token信息, 浏览器访问: http://localhost:8081/test/tokenInfo
|
||||
@Mapping("tokenInfo")
|
||||
public AjaxJson tokenInfo() {
|
||||
System.out.println("======================= 进入方法,打印当前token信息 ========================= ");
|
||||
SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
|
||||
System.out.println(tokenInfo);
|
||||
return AjaxJson.getSuccessData(tokenInfo);
|
||||
}
|
||||
|
||||
// 测试注解式鉴权, 浏览器访问: http://localhost:8081/test/atCheck
|
||||
@SaCheckLogin // 注解式鉴权:当前会话必须登录才能通过
|
||||
@SaCheckRole("super-admin") // 注解式鉴权:当前会话必须具有指定角色标识才能通过
|
||||
@SaCheckPermission("user-add") // 注解式鉴权:当前会话必须具有指定权限才能通过
|
||||
@Mapping("atCheck")
|
||||
public AjaxJson atCheck() {
|
||||
System.out.println("======================= 进入方法,测试注解鉴权接口 ========================= ");
|
||||
System.out.println("只有通过注解鉴权,才能进入此方法");
|
||||
// StpUtil.checkActiveTimeout();
|
||||
// StpUtil.updateLastActiveToNow();
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
// 测试注解式鉴权, 浏览器访问: http://localhost:8081/test/atJurOr
|
||||
@Mapping("atJurOr")
|
||||
@SaCheckPermission(value = {"user-add", "user-all", "user-delete"}, mode = SaMode.OR) // 注解式鉴权:只要具有其中一个权限即可通过校验
|
||||
public AjaxJson atJurOr() {
|
||||
return AjaxJson.getSuccessData("用户信息");
|
||||
}
|
||||
|
||||
// [活动时间] 续签: http://localhost:8081/test/rene
|
||||
@Mapping("rene")
|
||||
public AjaxJson rene() {
|
||||
StpUtil.checkActiveTimeout();
|
||||
StpUtil.updateLastActiveToNow();
|
||||
return AjaxJson.getSuccess("续签成功");
|
||||
}
|
||||
|
||||
// 测试踢人下线 浏览器访问: http://localhost:8081/test/kickOut
|
||||
@Mapping("kickOut")
|
||||
public AjaxJson kickOut() {
|
||||
// 先登录上
|
||||
StpUtil.login(10001);
|
||||
// 踢下线
|
||||
StpUtil.kickout(10001);
|
||||
// 再尝试获取
|
||||
StpUtil.getLoginId();
|
||||
// 返回
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
// 测试登录接口, 按照设备类型登录, 浏览器访问: http://localhost:8081/test/login2
|
||||
@Mapping("login2")
|
||||
public AjaxJson login2(@Param(defaultValue="10001") String id, @Param(defaultValue="PC") String device) {
|
||||
StpUtil.login(id, device);
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
// 测试身份临时切换: http://localhost:8081/test/switchTo
|
||||
@Mapping("switchTo")
|
||||
public AjaxJson switchTo() {
|
||||
System.out.println("当前会话身份:" + StpUtil.getLoginIdDefaultNull());
|
||||
System.out.println("是否正在身份临时切换中: " + StpUtil.isSwitch());
|
||||
StpUtil.switchTo(10044, () -> {
|
||||
System.out.println("是否正在身份临时切换中: " + StpUtil.isSwitch());
|
||||
System.out.println("当前会话身份已被切换为:" + StpUtil.getLoginId());
|
||||
});
|
||||
System.out.println("是否正在身份临时切换中: " + StpUtil.isSwitch());
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
// 测试会话治理 浏览器访问: http://localhost:8081/test/search
|
||||
@Mapping("search")
|
||||
public AjaxJson search() {
|
||||
System.out.println("--------------");
|
||||
Ttime t = new Ttime().start();
|
||||
List<String> tokenValue = StpUtil.searchTokenValue("8feb8265f773", 0, 10, true);
|
||||
for (String v : tokenValue) {
|
||||
// SaSession session = StpUtil.getSessionBySessionId(sid);
|
||||
System.out.println(v);
|
||||
}
|
||||
System.out.println("用时:" + t.end().toString());
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
// 测试指定设备类型登录 浏览器访问: http://localhost:8081/test/loginByDevice
|
||||
@Mapping("loginByDevice")
|
||||
public AjaxJson loginByDevice() {
|
||||
System.out.println("--------------");
|
||||
StpUtil.login(10001, "PC");
|
||||
return AjaxJson.getSuccessData("登录成功");
|
||||
}
|
||||
|
||||
|
||||
// 测试 浏览器访问: http://localhost:8081/test/test
|
||||
@Mapping("test")
|
||||
public AjaxJson test() {
|
||||
System.out.println("进来了");
|
||||
return AjaxJson.getSuccess("访问成功");
|
||||
}
|
||||
|
||||
// 测试 浏览器访问: http://localhost:8081/test/test2
|
||||
@Mapping("test2")
|
||||
public AjaxJson test2() {
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package com.pj.test;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import org.noear.solon.annotation.Controller;
|
||||
import org.noear.solon.annotation.Mapping;
|
||||
|
||||
/**
|
||||
* 登录测试
|
||||
* @author click33
|
||||
* @author noear
|
||||
*/
|
||||
@Controller
|
||||
@Mapping("/user/")
|
||||
public class UserController {
|
||||
|
||||
// 测试登录,浏览器访问: http://localhost:8081/user/doLogin?username=zhang&password=123456
|
||||
@Mapping("doLogin")
|
||||
public String doLogin(String username, String password) {
|
||||
// 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对
|
||||
if("zhang".equals(username) && "123456".equals(password)) {
|
||||
StpUtil.login(10001);
|
||||
return "登录成功";
|
||||
}
|
||||
return "登录失败";
|
||||
}
|
||||
|
||||
// 查询登录状态,浏览器访问: http://localhost:8081/user/isLogin
|
||||
@Mapping("isLogin")
|
||||
public String isLogin(String username, String password) {
|
||||
return "当前会话是否登录:" + StpUtil.isLogin();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package com.pj.util;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* ajax请求返回Json格式数据的封装
|
||||
*/
|
||||
public class AjaxJson implements Serializable{
|
||||
|
||||
private static final long serialVersionUID = 1L; // 序列化版本号
|
||||
|
||||
public static final int CODE_SUCCESS = 200; // 成功状态码
|
||||
public static final int CODE_ERROR = 500; // 错误状态码
|
||||
public static final int CODE_WARNING = 501; // 警告状态码
|
||||
public static final int CODE_NOT_JUR = 403; // 无权限状态码
|
||||
public static final int CODE_NOT_LOGIN = 401; // 未登录状态码
|
||||
public static final int CODE_INVALID_REQUEST = 400; // 无效请求状态码
|
||||
|
||||
public int code; // 状态码
|
||||
public String msg; // 描述信息
|
||||
public Object data; // 携带对象
|
||||
public Long dataCount; // 数据总数,用于分页
|
||||
|
||||
/**
|
||||
* 返回code
|
||||
* @return
|
||||
*/
|
||||
public int getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给msg赋值,连缀风格
|
||||
*/
|
||||
public AjaxJson setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
return this;
|
||||
}
|
||||
public String getMsg() {
|
||||
return this.msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给data赋值,连缀风格
|
||||
*/
|
||||
public AjaxJson setData(Object data) {
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将data还原为指定类型并返回
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getData(Class<T> cs) {
|
||||
return (T) data;
|
||||
}
|
||||
|
||||
// ============================ 构建 ==================================
|
||||
|
||||
public AjaxJson(int code, String msg, Object data, Long dataCount) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
this.data = data;
|
||||
this.dataCount = dataCount;
|
||||
}
|
||||
|
||||
// 返回成功
|
||||
public static AjaxJson getSuccess() {
|
||||
return new AjaxJson(CODE_SUCCESS, "ok", null, null);
|
||||
}
|
||||
public static AjaxJson getSuccess(String msg) {
|
||||
return new AjaxJson(CODE_SUCCESS, msg, null, null);
|
||||
}
|
||||
public static AjaxJson getSuccess(String msg, Object data) {
|
||||
return new AjaxJson(CODE_SUCCESS, msg, data, null);
|
||||
}
|
||||
public static AjaxJson getSuccessData(Object data) {
|
||||
return new AjaxJson(CODE_SUCCESS, "ok", data, null);
|
||||
}
|
||||
public static AjaxJson getSuccessArray(Object... data) {
|
||||
return new AjaxJson(CODE_SUCCESS, "ok", data, null);
|
||||
}
|
||||
|
||||
// 返回失败
|
||||
public static AjaxJson getError() {
|
||||
return new AjaxJson(CODE_ERROR, "error", null, null);
|
||||
}
|
||||
public static AjaxJson getError(String msg) {
|
||||
return new AjaxJson(CODE_ERROR, msg, null, null);
|
||||
}
|
||||
|
||||
// 返回警告
|
||||
public static AjaxJson getWarning() {
|
||||
return new AjaxJson(CODE_ERROR, "warning", null, null);
|
||||
}
|
||||
public static AjaxJson getWarning(String msg) {
|
||||
return new AjaxJson(CODE_WARNING, msg, null, null);
|
||||
}
|
||||
|
||||
// 返回未登录
|
||||
public static AjaxJson getNotLogin() {
|
||||
return new AjaxJson(CODE_NOT_LOGIN, "未登录,请登录后再次访问", null, null);
|
||||
}
|
||||
|
||||
// 返回没有权限的
|
||||
public static AjaxJson getNotJur(String msg) {
|
||||
return new AjaxJson(CODE_NOT_JUR, msg, null, null);
|
||||
}
|
||||
|
||||
// 返回一个自定义状态码的
|
||||
public static AjaxJson get(int code, String msg){
|
||||
return new AjaxJson(code, msg, null, null);
|
||||
}
|
||||
|
||||
// 返回分页和数据的
|
||||
public static AjaxJson getPageData(Long dataCount, Object data){
|
||||
return new AjaxJson(CODE_SUCCESS, "ok", data, dataCount);
|
||||
}
|
||||
|
||||
// 返回,根据受影响行数的(大于0=ok,小于0=error)
|
||||
public static AjaxJson getByLine(int line){
|
||||
if(line > 0){
|
||||
return getSuccess("ok", line);
|
||||
}
|
||||
return getError("error").setData(line);
|
||||
}
|
||||
|
||||
// 返回,根据布尔值来确定最终结果的 (true=ok,false=error)
|
||||
public static AjaxJson getByBoolean(boolean b){
|
||||
return b ? getSuccess("ok") : getError("error");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public String toString() {
|
||||
String data_string = null;
|
||||
if(data == null){
|
||||
|
||||
} else if(data instanceof List){
|
||||
data_string = "List(length=" + ((List)data).size() + ")";
|
||||
} else {
|
||||
data_string = data.toString();
|
||||
}
|
||||
return "{"
|
||||
+ "\"code\": " + this.getCode()
|
||||
+ ", \"msg\": \"" + this.getMsg() + "\""
|
||||
+ ", \"data\": " + data_string
|
||||
+ ", \"dataCount\": " + dataCount
|
||||
+ "}";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.pj.util;
|
||||
|
||||
|
||||
/**
|
||||
* 用于测试用时
|
||||
* @author click33
|
||||
*
|
||||
*/
|
||||
public class Ttime {
|
||||
|
||||
private long start=0; //开始时间
|
||||
private long end=0; //结束时间
|
||||
|
||||
public static Ttime t = new Ttime(); //static快捷使用
|
||||
|
||||
/**
|
||||
* 开始计时
|
||||
* @return
|
||||
*/
|
||||
public Ttime start() {
|
||||
start=System.currentTimeMillis();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 结束计时
|
||||
*/
|
||||
public Ttime end() {
|
||||
end=System.currentTimeMillis();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 返回所用毫秒数
|
||||
*/
|
||||
public long returnMs() {
|
||||
return end-start;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化输出结果
|
||||
*/
|
||||
public void outTime() {
|
||||
System.out.println(this.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束并格式化输出结果
|
||||
*/
|
||||
public void endOutTime() {
|
||||
this.end().outTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return (returnMs() + 0.0) / 1000 + "s"; // 格式化为:0.01s
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
# 端口
|
||||
server:
|
||||
port: 8081
|
||||
|
||||
# sa-token 配置
|
||||
sa-token:
|
||||
# token 名称 (同时也是 cookie 名称)
|
||||
token-name: satoken
|
||||
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||
timeout: 2592000
|
||||
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||
active-timeout: -1
|
||||
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||
is-concurrent: true
|
||||
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||
is-share: true
|
||||
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||
token-style: uuid
|
||||
# 是否输出操作日志
|
||||
is-log: true
|
||||
|
||||
|
||||
|
||||
sa-token-dao:
|
||||
config: |
|
||||
singleServerConfig:
|
||||
password: "123456"
|
||||
address: "redis://localhost:6379"
|
||||
database: 0
|
||||
|
||||
|
||||
|
||||
@@ -10,14 +10,13 @@
|
||||
<parent>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon-parent</artifactId>
|
||||
<version>2.2.3</version>
|
||||
<version>2.4.0</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<solon.version>2.2.3</solon.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
</properties>
|
||||
@@ -28,13 +27,11 @@
|
||||
<dependency>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon-web</artifactId>
|
||||
<version>${solon.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon.logging</artifactId>
|
||||
<version>${solon.version}</version>
|
||||
<artifactId>solon.logging.simple</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Sa-Token 权限认证, 在线文档:https://sa-token.cc/ -->
|
||||
@@ -45,18 +42,11 @@
|
||||
</dependency>
|
||||
|
||||
<!-- sa-token整合redis (使用jdk默认序列化方式) -->
|
||||
<!-- <dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-redisx</artifactId>
|
||||
<version>${sa-token.version}</version>
|
||||
</dependency> -->
|
||||
|
||||
|
||||
<!-- 提供redis连接池 -->
|
||||
<!-- <dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
</dependency> -->
|
||||
</dependency>
|
||||
|
||||
<!-- hutool工具类,用来生成雪花算法唯一id -->
|
||||
<!-- <dependency>
|
||||
|
||||
+8
-1
@@ -1,14 +1,16 @@
|
||||
package com.pj.satoken;
|
||||
|
||||
|
||||
import cn.dev33.satoken.dao.SaTokenDao;
|
||||
import cn.dev33.satoken.dao.SaTokenDaoOfRedis;
|
||||
import cn.dev33.satoken.solon.integration.SaTokenInterceptor;
|
||||
import org.noear.solon.Solon;
|
||||
import org.noear.solon.annotation.Bean;
|
||||
import org.noear.solon.annotation.Configuration;
|
||||
|
||||
import com.pj.util.AjaxJson;
|
||||
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import org.noear.solon.annotation.Inject;
|
||||
|
||||
|
||||
/**
|
||||
@@ -57,4 +59,9 @@ public class SaTokenConfigure {
|
||||
;
|
||||
});
|
||||
}
|
||||
//如果需要 redis dao,加这段代表
|
||||
// @Bean
|
||||
// public SaTokenDao saTokenDaoInit(@Inject("${sa-token-dao.redis}") SaTokenDaoOfRedis saTokenDao) {
|
||||
// return saTokenDao;
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -18,31 +18,14 @@ sa-token:
|
||||
token-style: uuid
|
||||
# 是否输出操作日志
|
||||
is-log: true
|
||||
|
||||
solon:
|
||||
# redis配置
|
||||
|
||||
|
||||
sa-token-dao: #名字可以随意取
|
||||
redis:
|
||||
# Redis数据库索引(默认为0)
|
||||
database: 0
|
||||
# Redis服务器地址
|
||||
host: 127.0.0.1
|
||||
# Redis服务器连接端口
|
||||
port: 6379
|
||||
# Redis服务器连接密码(默认为空)
|
||||
password:
|
||||
# 连接超时时间(毫秒)
|
||||
timeout: 10000ms
|
||||
lettuce:
|
||||
pool:
|
||||
# 连接池最大连接数
|
||||
max-active: 200
|
||||
# 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
max-wait: -1ms
|
||||
# 连接池中的最大空闲连接
|
||||
max-idle: 10
|
||||
# 连接池中的最小空闲连接
|
||||
min-idle: 0
|
||||
|
||||
server: "localhost:6379"
|
||||
password: 123456
|
||||
db: 1
|
||||
maxTotal: 200
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
+12
-2
@@ -1,10 +1,11 @@
|
||||
package com.pj.test;
|
||||
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.spring.SpringMVCUtil;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
|
||||
/**
|
||||
* 测试专用Controller
|
||||
* @author click33
|
||||
@@ -27,4 +28,13 @@ public class TestController {
|
||||
return SaResult.ok();
|
||||
}
|
||||
|
||||
// 测试 浏览器访问: http://localhost:8081/test/getRequestPath
|
||||
@RequestMapping("getRequestPath")
|
||||
public SaResult getRequestPath() {
|
||||
System.out.println("-------------- 测试请求 path 获取");
|
||||
System.out.println("request.getRequestURI() " + SpringMVCUtil.getRequest().getRequestURI());
|
||||
System.out.println("saRequest.getRequestPath() " + SaHolder.getRequest().getRequestPath());
|
||||
return SaResult.ok();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ sa-token:
|
||||
# 是否输出操作日志
|
||||
is-log: true
|
||||
|
||||
spring:
|
||||
spring:
|
||||
data:
|
||||
# redis配置
|
||||
redis:
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
<parent>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon-parent</artifactId>
|
||||
<version>2.2.3</version>
|
||||
<version>2.4.0</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
<solon.version>2.2.3</solon.version>
|
||||
</properties>
|
||||
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
<parent>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon-parent</artifactId>
|
||||
<version>2.2.3</version>
|
||||
<version>2.4.0</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
<parent>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon-parent</artifactId>
|
||||
<version>2.2.3</version>
|
||||
<version>2.4.0</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
<parent>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon-parent</artifactId>
|
||||
<version>2.2.3</version>
|
||||
<version>2.4.0</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -11,13 +11,14 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.5.14</version>
|
||||
<!--<version>2.3.0.RELEASE</version>-->
|
||||
<!-- <version>1.5.9.RELEASE</version> -->
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
<java.run.main.class>com.pj.SaTokenApplication</java.run.main.class>
|
||||
</properties>
|
||||
|
||||
@@ -72,7 +73,7 @@
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<!-- 构建配置 -->
|
||||
|
||||
@@ -23,5 +23,5 @@ public class NotFoundHandle implements ErrorController {
|
||||
response.setStatus(200);
|
||||
return SaResult.get(404, "not found", null);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.pj.test;
|
||||
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.spring.SpringMVCUtil;
|
||||
import cn.dev33.satoken.stp.SaLoginConfig;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
@@ -41,4 +43,13 @@ public class TestController {
|
||||
return SaResult.ok();
|
||||
}
|
||||
|
||||
// 测试 浏览器访问: http://localhost:8081/test/getRequestPath
|
||||
@RequestMapping("getRequestPath")
|
||||
public SaResult getRequestPath() {
|
||||
System.out.println("------------ 测试访问路径获取 ");
|
||||
System.out.println("SpringMVCUtil.getRequest().getRequestURI() " + SpringMVCUtil.getRequest().getRequestURI());
|
||||
System.out.println("SaHolder.getRequest().getRequestPath() " + SaHolder.getRequest().getRequestPath());
|
||||
return SaResult.ok();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ sa-token:
|
||||
# 是否输出操作日志
|
||||
is-log: true
|
||||
|
||||
spring:
|
||||
spring:
|
||||
# redis配置
|
||||
redis:
|
||||
# Redis数据库索引(默认为0)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
package com.pj;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
|
||||
/**
|
||||
* Sa-Token整合webflux 示例 (springboot3)
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@ sa-token:
|
||||
# 是否输出操作日志
|
||||
is-log: true
|
||||
|
||||
spring:
|
||||
spring:
|
||||
# redis配置
|
||||
redis:
|
||||
# Redis数据库索引(默认为0)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -19,7 +19,7 @@ sa-token:
|
||||
# 是否输出操作日志
|
||||
is-log: true
|
||||
|
||||
spring:
|
||||
spring:
|
||||
# redis配置
|
||||
redis:
|
||||
# Redis数据库索引(默认为0)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.35.0.RC</sa-token.version>
|
||||
<sa-token.version>1.37.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<description>Sa-Token Dependencies</description>
|
||||
|
||||
<properties>
|
||||
<revision>1.35.0.RC</revision>
|
||||
<revision>1.37.0</revision>
|
||||
|
||||
<!-- 统一定义依赖版本号 -->
|
||||
<springboot.version>2.5.15</springboot.version>
|
||||
@@ -23,9 +23,9 @@
|
||||
<servlet-api.version>3.1.0</servlet-api.version>
|
||||
<jakarta-servlet-api.version>6.0.0</jakarta-servlet-api.version>
|
||||
<thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
|
||||
<solon.version>2.2.3</solon.version>
|
||||
<noear-redisx.version>1.4.7</noear-redisx.version>
|
||||
<noear-snack3.version>3.2.65</noear-snack3.version>
|
||||
<solon.version>2.5.3</solon.version>
|
||||
<noear-redisx.version>1.6.0</noear-redisx.version>
|
||||
<noear-snack3.version>3.2.80</noear-snack3.version>
|
||||
<jfinal.version>4.9.17</jfinal.version>
|
||||
<jboot.version>3.14.4</jboot.version>
|
||||
<commons-pool2.version>2.5.0</commons-pool2.version>
|
||||
@@ -140,6 +140,12 @@
|
||||
</dependency>
|
||||
|
||||
<!-- Redisson 相关操作API -->
|
||||
<dependency>
|
||||
<groupId>org.redisson</groupId>
|
||||
<artifactId>redisson</artifactId>
|
||||
<version>${redisson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.redisson</groupId>
|
||||
<artifactId>redisson-spring-boot-starter</artifactId>
|
||||
|
||||
+2
-14
@@ -1,7 +1,7 @@
|
||||
<p align="center">
|
||||
<img alt="logo" src="https://sa-token.cc/logo.png" width="150" height="150">
|
||||
</p>
|
||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">Sa-Token v1.35.0.RC</h1>
|
||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">Sa-Token v1.37.0</h1>
|
||||
<h5 align="center">一个轻量级 Java 权限认证框架,让鉴权变得简单、优雅!</h5>
|
||||
<p align="center" class="badge-box">
|
||||
<a href="https://gitee.com/dromara/sa-token/stargazers"><img src="https://gitee.com/dromara/sa-token/badge/star.svg?theme=gvp"></a>
|
||||
@@ -136,18 +136,6 @@ Sa-Token 目前主要五大功能模块:登录认证、权限认证、单点
|
||||
|
||||
|
||||
## 交流群
|
||||
QQ交流群:707350988 [点击加入](https://jq.qq.com/?_wv=1027&k=tqbzHT2D)
|
||||
加入 Sa-Token 框架 QQ、微信讨论群:[点击加入](/more/join-group.md)
|
||||
|
||||
微信交流群:
|
||||
|
||||

|
||||
|
||||
(扫码添加微信,备注:sa-token,邀您加入群聊)
|
||||
|
||||
<br>
|
||||
|
||||
加入群聊的好处:
|
||||
- 第一时间收到框架更新通知。
|
||||
- 第一时间收到框架 bug 通知。
|
||||
- 第一时间收到新增开源案例通知。
|
||||
- 和众多大佬一起互相 (huá shǔi) 交流 (mō yú)。
|
||||
|
||||
+57
-9
@@ -18,7 +18,7 @@
|
||||
<div class="logo-box">
|
||||
<img src="logo.png" title="logo" />
|
||||
<h1 class="logo-text">Sa-Token</h1>
|
||||
<sub>v1.35.0.RC</sub>
|
||||
<sub>v1.37.0</sub>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
@@ -28,6 +28,8 @@
|
||||
</div>
|
||||
<select class="select-version p-none" onchange="location.href=this.value">
|
||||
<option value="doc.html">最新版</option>
|
||||
<option value="v/v1.36.0/doc.html">v1.36.0</option>
|
||||
<option value="v/v1.35.0/doc.html">v1.35.0</option>
|
||||
<option value="v/v1.34.0/doc.html">v1.34.0</option>
|
||||
<option value="v/v1.33.0/doc.html">v1.33.0</option>
|
||||
<option value="v/v1.32.0/doc.html">v1.32.0</option>
|
||||
@@ -136,10 +138,21 @@
|
||||
<div class="main-box">
|
||||
<div id="app">加载中...</div>
|
||||
</div>
|
||||
|
||||
<!-- 万维广告div -->
|
||||
<div style="position: fixed; right: 0; bottom: 0; z-index: 10000; border: 0px #aaa solid;">
|
||||
<div class="wwads-cn wwads-vertical" data-id="88" style="max-width:150px"></div>
|
||||
</div>
|
||||
|
||||
<!-- 小助手div -->
|
||||
<div class="p-none help-btn-box" style="position: fixed; right: 40px; bottom: 330px; z-index: 10000; border: 0px #aaa solid;">
|
||||
<div class="help-tips" style="position: relative; left: -30px; top: -10px;"></div>
|
||||
<div class="help-btn" style="width: 60px; height: 60px; text-align: center; border-radius: 50%; background-color: #42b983; cursor: pointer;">
|
||||
<span style="font-size: 18px; color: #FFF; line-height: 60px;">Help</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- UI逐渐显现 -->
|
||||
<style type="text/css">
|
||||
body{opacity: 0.01; transition: opacity 0.5s; background-color: #FFF;}
|
||||
@@ -151,9 +164,10 @@
|
||||
</script>
|
||||
|
||||
<!-- -->
|
||||
<script src="./static/docsify-plugin.js"></script>
|
||||
<script src="./static/docsify-plugin.js?v=6"></script>
|
||||
<script src="./static/is-star-plugin.js?v=6"></script>
|
||||
<script>
|
||||
var saTokenTopVersion = '1.35.0.RC'; // Sa-Token最新版本
|
||||
var saTokenTopVersion = '1.37.0'; // Sa-Token最新版本
|
||||
var name = '<img style="width: 60px; height: 60px; vertical-align: middle;" src="logo.png" alt="logo" /> ';
|
||||
name += '<b style="font-size: 28px; vertical-align: middle;">Sa-Token</b> <sub>v' + saTokenTopVersion + '</sub>';
|
||||
window.$docsify = {
|
||||
@@ -187,7 +201,7 @@
|
||||
tabHeadings: true // 用标题+粗体来定制选项卡
|
||||
},
|
||||
// 自定义插件
|
||||
plugins: [myDocsifyPlugin],
|
||||
plugins: [myDocsifyPlugin, window.isStarPlugin],
|
||||
}
|
||||
</script>
|
||||
<script src="static/docsify.min.js"></script>
|
||||
@@ -236,12 +250,9 @@
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="https://cdn.wwads.cn/js/makemoney.js" async></script>
|
||||
<!-- 万维广告 -->
|
||||
<script data-mode="hash" type="text/javascript" src="https://cdn.wwads.cn/js/makemoney.js" async></script>
|
||||
|
||||
<!-- 友盟 -->
|
||||
<div style="height: 0px; overflow: hidden;">
|
||||
<script type="text/javascript" src="https://s4.cnzz.com/z_stat.php?id=1279646043&web_id=1279646043"></script>
|
||||
</div>
|
||||
<!-- 百度统计 -->
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
@@ -261,6 +272,43 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- 小助手提示 -->
|
||||
<script>
|
||||
$('.help-btn').click(function(){
|
||||
var str = `
|
||||
<div class="xiaozhushou-intro">
|
||||
<p>1、你在使用 Sa-Token 时遇到任何技术难题,可以向 < sa-token 小助手 > 求助咨询。</p>
|
||||
<p>2、该小助手不属于商业运营,求助咨询完全免费。</p>
|
||||
<p>3、目前该小助手属于试运营阶段,每天只能提供大约 1 小时的求助时间。</p>
|
||||
<p>4、根据运营效果反馈,我们日后可能会提高求助时间,但也可能关闭此功能。</p>
|
||||
<p>5、该小助手由企业微信提供平台支持,感谢企业微信。</p>
|
||||
<p>6、不是 AI 是真人,不是 AI 是真人,不是 AI 是真人,重说三!</p>
|
||||
<p style="margin-top: 30px;">打开方式:</p>
|
||||
<p>1、如果你是使用 PC 端微信,请点此链接:<a href="https://work.weixin.qq.com/kfid/kfcdd45c432fee9655f" target="_blank">https://work.weixin.qq.com/kfid/kfcdd45c432fee9655f</a></p>
|
||||
<p>2、如果你是使用手机端微信,请扫码:</p>
|
||||
<p><img src="https://oss.dev33.cn/sa-token/sa-token-xiaozhushou.jpg" width="200px"></p>
|
||||
</div>
|
||||
`;
|
||||
layer.alert(str, {
|
||||
title: '技术求助',
|
||||
area: '550px',
|
||||
offset: '10%',
|
||||
})
|
||||
})
|
||||
try{
|
||||
// 给个小提示
|
||||
const index = layer.tips('框架技术支持,点此求助', '.help-tips', {
|
||||
tips: [1, '#000'] ,//还可配置颜色
|
||||
time: 5000,
|
||||
});
|
||||
// 改为 fixed 定位,否则它会随着滚动条移动,样式就跑偏了
|
||||
$('#layui-layer' + index).css('position', 'fixed');
|
||||
}catch(e){
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<!-- 修改背景颜色 -->
|
||||
<script>
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# Sa-Token 插件开发指南
|
||||
|
||||
> 注:为 Sa-Token 提交插件请在 sa-token-three-plugin 仓库进行:[点击跳转](https://gitee.com/sa-tokens/sa-token-three-plugin)
|
||||
|
||||
---
|
||||
|
||||
插件,从字面意思理解就是可拔插的组件,作用是在不改变 Sa-Token 现有架构的情况下,替换或扩展一部分底层代码逻辑。
|
||||
|
||||
+345
-171
@@ -4,16 +4,20 @@
|
||||
<meta charset="UTF-8">
|
||||
<title>Sa-Token</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta name="description" content="Sa-Token是一个java权限认证框架,功能全面,上手简单,登录认证、权限认证、Session会话、踢人下线、账号封禁、集成Redis、前后端分离、分布式会话、微服务网关鉴权、单点登录、OAuth2.0、临时Token验证、记住我模式、模拟他人账号、临时身份切换、多账号体系、注解式鉴权、路由拦截式鉴权、花式token、自动续签、同端互斥登录、会话治理、密码加密、jwt集成、Spring集成、WebFlux集成...,有了sa-token,你所有的权限认证问题,都不再是问题">
|
||||
<meta name="description"
|
||||
content="Sa-Token是一个java权限认证框架,功能全面,上手简单,登录认证、权限认证、Session会话、踢人下线、账号封禁、集成Redis、前后端分离、分布式会话、微服务网关鉴权、单点登录、OAuth2.0、临时Token验证、记住我模式、模拟他人账号、临时身份切换、多账号体系、注解式鉴权、路由拦截式鉴权、花式token、自动续签、同端互斥登录、会话治理、密码加密、jwt集成、Spring集成、WebFlux集成...,有了sa-token,你所有的权限认证问题,都不再是问题">
|
||||
<meta name="keywords" content="sa-token,sa-token框架,sa-token文档,java权限认证">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="logo.png">
|
||||
<link rel="stylesheet" href="static/index.css">
|
||||
<link rel="stylesheet" href="static/swiper/swiper-bundle.min.css">
|
||||
<link rel="stylesheet" href="static/swiper/index-swiper.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- 总盒子 -->
|
||||
<div class="z-div" style="">
|
||||
|
||||
<div class="z-div" style="">
|
||||
|
||||
<!-- ------------ 头部 ------------- -->
|
||||
<header class="doc-header">
|
||||
<div class="nav-left">
|
||||
@@ -41,13 +45,13 @@
|
||||
<span style="background-color: #F1FAFA;"></span>
|
||||
<span style="background-color: #f5f5d5;"></span>
|
||||
<span style="background-color: #d5f5f5;"></span>
|
||||
|
||||
|
||||
<span style="background-color: #f5e5f5;"></span>
|
||||
<span style="background-color: #E8E8FF;"></span>
|
||||
<span style="background-color: #f0f9eb;"></span>
|
||||
<span style="background-color: #ebe5dd;"></span>
|
||||
<span style="background-color: #e8f4ff;"></span>
|
||||
|
||||
|
||||
<!-- <span style="background-color: #F0DAD2;"></span> -->
|
||||
<!-- <span style="background-color: #f5d5d5;"></span> -->
|
||||
<!-- <span style="background-color: #FFFFE0;"></span> -->
|
||||
@@ -86,24 +90,26 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- github小章鱼图标 -->
|
||||
<a href="https://github.com/dromara/sa-token" target="_blank" class="github-corner" aria-label="View source on Github"
|
||||
style="position: fixed; right: -16px; padding-left: 0px;">
|
||||
<a href="https://github.com/dromara/sa-token" target="_blank" class="github-corner"
|
||||
aria-label="View source on Github" style="position: fixed; right: -16px; padding-left: 0px;">
|
||||
<svg viewBox="0 0 250 250" aria-hidden="true">
|
||||
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
|
||||
<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
|
||||
fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
|
||||
<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
|
||||
fill="currentColor" class="octo-body"></path>
|
||||
<path
|
||||
d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
|
||||
fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
|
||||
<path
|
||||
d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
|
||||
fill="currentColor" class="octo-body"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
|
||||
<!-- ------------ 海报部分 ------------- -->
|
||||
<div class="main-box">
|
||||
<div class="content-box">
|
||||
<!-- <div class="fenge"></div> -->
|
||||
<h1>Sa-Token<small>v1.35.0.RC</small></h1>
|
||||
<h1>Sa-Token<small>v1.37.0</small></h1>
|
||||
<div class="sub-title">一个轻量级 java 权限认证框架,让鉴权变得简单、优雅!</div>
|
||||
<div class="btn-box">
|
||||
<a class="abtn" href="https://github.com/dromara/sa-token" target="_blank">GitHub</a>
|
||||
@@ -113,17 +119,24 @@
|
||||
<!-- <a href="https://gitee.com/dromara/sa-token" target="_blank">集成案例</a> -->
|
||||
</div>
|
||||
<h4 align="center" class="badge-box">
|
||||
<a href="https://gitee.com/dromara/sa-token/stargazers"><img class="lazy" data-original="https://gitee.com/dromara/sa-token/badge/star.svg?theme=gvp"></a>
|
||||
<a href="https://gitee.com/dromara/sa-token/members"><img class="lazy" data-original="https://gitee.com/dromara/sa-token/badge/fork.svg?theme=gvp"></a>
|
||||
<a href="https://github.com/dromara/sa-token/stargazers"><img class="lazy" data-original="https://img.shields.io/github/stars/dromara/sa-token?style=flat-square&logo=GitHub"></a>
|
||||
<a href="https://github.com/dromara/sa-token/network/members"><img class="lazy" data-original="https://img.shields.io/github/forks/dromara/sa-token?style=flat-square&logo=GitHub"></a>
|
||||
<a href="https://github.com/dromara/sa-token/watchers"><img class="lazy" data-original="https://img.shields.io/github/watchers/dromara/sa-token?style=flat-square&logo=GitHub"></a>
|
||||
<a href="https://github.com/dromara/sa-token/issues"><img class="lazy" data-original="https://img.shields.io/github/issues/dromara/sa-token.svg?style=flat-square&logo=GitHub"></a>
|
||||
<a href="https://github.com/dromara/sa-token/blob/master/LICENSE"><img class="lazy" data-original="https://img.shields.io/github/license/dromara/sa-token.svg?style=flat-square"></a>
|
||||
<a href="https://gitee.com/dromara/sa-token/stargazers"><img class="lazy"
|
||||
data-original="https://gitee.com/dromara/sa-token/badge/star.svg?theme=gvp"></a>
|
||||
<a href="https://gitee.com/dromara/sa-token/members"><img class="lazy"
|
||||
data-original="https://gitee.com/dromara/sa-token/badge/fork.svg?theme=gvp"></a>
|
||||
<a href="https://github.com/dromara/sa-token/stargazers"><img class="lazy"
|
||||
data-original="https://img.shields.io/github/stars/dromara/sa-token?style=flat-square&logo=GitHub"></a>
|
||||
<a href="https://github.com/dromara/sa-token/network/members"><img class="lazy"
|
||||
data-original="https://img.shields.io/github/forks/dromara/sa-token?style=flat-square&logo=GitHub"></a>
|
||||
<a href="https://github.com/dromara/sa-token/watchers"><img class="lazy"
|
||||
data-original="https://img.shields.io/github/watchers/dromara/sa-token?style=flat-square&logo=GitHub"></a>
|
||||
<a href="https://github.com/dromara/sa-token/issues"><img class="lazy"
|
||||
data-original="https://img.shields.io/github/issues/dromara/sa-token.svg?style=flat-square&logo=GitHub"></a>
|
||||
<a href="https://github.com/dromara/sa-token/blob/master/LICENSE"><img class="lazy"
|
||||
data-original="https://img.shields.io/github/license/dromara/sa-token.svg?style=flat-square"></a>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- ------------ 支持特性 ------------- -->
|
||||
<div>
|
||||
<div class="feature-z s-width">
|
||||
@@ -134,7 +147,7 @@
|
||||
<p>多端登录、单端登录、同端互斥登录、七天免登录…… 多种登录策略只需改个配置即可完成</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<h2>🔑️ 权限认证</h2>
|
||||
<h2>🔑️️ 权限认证</h2>
|
||||
<p>权限认证、角色认证、会话二级认证、注解鉴权、路由鉴权……多种姿势灵活鉴权</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
@@ -142,11 +155,11 @@
|
||||
<p>强制注销、踢人下线、账号封禁、身份切换、自动续签 …… 提供完善的会话管理方案</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<h2>🔎️ Redis集成</h2>
|
||||
<h2>🔎 Redis集成</h2>
|
||||
<p>提供 Redis 集成方案、项目重启数据不丢失、多系统数据互通,可自定义数据持久化策略</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<h2>🚀️ 前后端分离</h2>
|
||||
<h2>🚀️️ 前后端分离</h2>
|
||||
<p>内置多种 Token 读取策略,适配APP、小程序、SPA单页应用等前后端分离场景</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
@@ -172,14 +185,55 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- ------------ 曾获荣誉 ------------- -->
|
||||
<div>
|
||||
<div class="feature-z ry-kuai">
|
||||
<div class="s-fenge"></div>
|
||||
<h2 class="s-title">曾获荣誉</h2>
|
||||
<div class="ry-box">
|
||||
<div class="swiper mySwiper">
|
||||
<div class="swiper-wrapper">
|
||||
<div class="swiper-slide">
|
||||
<img src="https://oss.dev33.cn/sa-token/awards/gpv.jpg?x-oss-process=style/st" /> <br>
|
||||
<p>GVP - Gitee 最有价值开源项目</p>
|
||||
</div>
|
||||
<div class="swiper-slide">
|
||||
<img src="https://oss.dev33.cn/sa-token/awards/osc-2021.jpg?x-oss-process=style/st"/> <br>
|
||||
<p>OSCHINA 2021 人气指数 TOP 30 开源项目</p>
|
||||
</div>
|
||||
<div class="swiper-slide swiper-slide-tx1">
|
||||
<img src="https://oss.dev33.cn/sa-token/awards/osc-2022.jpg?x-oss-process=style/st" /> <br>
|
||||
<p>OSCHINA 2022 年度最火热中国开源项目社区</p>
|
||||
</div>
|
||||
<div class="swiper-slide">
|
||||
<img src="https://oss.dev33.cn/sa-token/awards/kexin.jpg?x-oss-process=style/st" /> <br>
|
||||
<p>可信开源社区共同体预备成员</p>
|
||||
</div>
|
||||
<!-- <div class="swiper-slide" style="width: 750px;">
|
||||
<img src="https://oss.dev33.cn/sa-token/awards/gitee-star-10k.png" /> <br>
|
||||
<p>Gitee stars 超 10k+</p>
|
||||
</div>
|
||||
<div class="swiper-slide" style="width: 750px;">
|
||||
<img src="https://oss.dev33.cn/sa-token/awards/github-star-10k.png" /> <br>
|
||||
<p>GitHub stars 超 10k+</p>
|
||||
</div> -->
|
||||
</div>
|
||||
<div class="swiper-button-next"></div>
|
||||
<div class="swiper-button-prev"></div>
|
||||
<div class="swiper-pagination"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ------------ 开源案例 ------------- -->
|
||||
<div>
|
||||
<div class="feature-z s-width">
|
||||
<div class="s-fenge"></div>
|
||||
<h2 class="s-title">优秀开源集成案例</h2>
|
||||
<!-- <div class="s-fenge"></div> -->
|
||||
<h2 class="s-title" style="margin-top: 40px;">优秀开源集成案例</h2>
|
||||
<div class="feature-box s-case-box">
|
||||
<!-- Snowy 5.5k -->
|
||||
<!-- Snowy 6.1K -->
|
||||
<div class="s-case">
|
||||
<a href="https://gitee.com/xiaonuobase/snowy" target="_blank" class="s-case-link">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/case/case--snowy.png">
|
||||
@@ -188,34 +242,37 @@
|
||||
<span class="s-author"> 小诺开源技术 </span>
|
||||
<p class="s-case-intro">国内首个国密前后分离快速开发平台,基于Vue3、Antdv、SaToken</p>
|
||||
</div>
|
||||
<!-- SpringBoot_v2 5.3k -->
|
||||
<div class="s-case">
|
||||
<a href="https://gitee.com/bdj/SpringBoot_v2" target="_blank" class="s-case-link">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/case/case--springboot_v2.png">
|
||||
</a>
|
||||
<h3 class="s-case-title">SpringBoot_v2</h3>
|
||||
<span class="s-author">开源oschina</span>
|
||||
<p class="s-case-intro">努力打造 springboot 框架的极致细腻的脚手架,原生纯净。</p>
|
||||
</div>
|
||||
<!-- RuoYi-Vue-Plus 4.1k -->
|
||||
<!-- RuoYi-Vue-Plus 5.9k -->
|
||||
<div class="s-case">
|
||||
<a href="https://gitee.com/dromara/RuoYi-Vue-Plus" target="_blank" class="s-case-link">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/case/case--ruoyi-vue-plus.png">
|
||||
<img class="lazy"
|
||||
data-original="https://oss.dev33.cn/sa-token/case/case--ruoyi-vue-plus.png">
|
||||
</a>
|
||||
<h3 class="s-case-title">RuoYi-Vue-Plus</h3>
|
||||
<span class="s-author"> 疯狂的狮子Li </span>
|
||||
<p class="s-case-intro">重写 RuoYi-Vue 所有功能,集成 Sa-Token、Mybatis-Plus、Hutool 定期同步</p>
|
||||
</div>
|
||||
<!-- RuoYi-Cloud-Plus 1.5K -->
|
||||
<!-- SpringBoot_v2 5.5k -->
|
||||
<div class="s-case">
|
||||
<a href="https://gitee.com/bdj/SpringBoot_v2" target="_blank" class="s-case-link">
|
||||
<img class="lazy"
|
||||
data-original="https://oss.dev33.cn/sa-token/case/case--springboot_v2.png">
|
||||
</a>
|
||||
<h3 class="s-case-title">SpringBoot_v2</h3>
|
||||
<span class="s-author">开源oschina</span>
|
||||
<p class="s-case-intro">努力打造 springboot 框架的极致细腻的脚手架,原生纯净。</p>
|
||||
</div>
|
||||
<!-- RuoYi-Cloud-Plus 2.4K -->
|
||||
<div class="s-case">
|
||||
<a href="https://gitee.com/dromara/RuoYi-Cloud-Plus" target="_blank" class="s-case-link">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/case/case--ruoyi-cloud-plus.png">
|
||||
<img class="lazy"
|
||||
data-original="https://oss.dev33.cn/sa-token/case/case--ruoyi-cloud-plus.png">
|
||||
</a>
|
||||
<h3 class="s-case-title">RuoYi-Cloud-Plus</h3>
|
||||
<span class="s-author"> 疯狂的狮子Li </span>
|
||||
<p class="s-case-intro">重写 RuoYi-Cloud 所有功能 整合 SpringCloudAlibaba、Dubbo3.0、Sa-Token</p>
|
||||
</div>
|
||||
<!-- Sa-Plus 1K -->
|
||||
<!-- Sa-Plus 1.1K -->
|
||||
<div class="s-case">
|
||||
<a href="https://gitee.com/click33/sa-plus" target="_blank" class="s-case-link">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/case/case--sa-plus.png">
|
||||
@@ -224,10 +281,11 @@
|
||||
<span class="s-author"> 孔明 </span>
|
||||
<p class="s-case-intro">一个基于 SpringBoot 的快速开发框架,内置代码生成器</p>
|
||||
</div>
|
||||
<!-- EasyAdmin 878 -->
|
||||
<!-- EasyAdmin 996 -->
|
||||
<div class="s-case">
|
||||
<a href="https://gitee.com/lakernote/easy-admin" target="_blank" class="s-case-link">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/case/case--easy-admin.png">
|
||||
<img class="lazy"
|
||||
data-original="https://oss.dev33.cn/sa-token/case/case--easy-admin.png">
|
||||
</a>
|
||||
<h3 class="s-case-title">EasyAdmin</h3>
|
||||
<span class="s-author"> laker </span>
|
||||
@@ -237,14 +295,20 @@
|
||||
<div class="re-text">
|
||||
<span>
|
||||
如果您的开源项目也使用了 Sa-Token,您可以
|
||||
<a href="https://gitee.com/sa-token/awesome-sa-token" target="_blank" style="text-decoration: none;">在此</a>
|
||||
<a href="https://gitee.com/sa-token/awesome-sa-token" target="_blank"
|
||||
style="text-decoration: none;">在此</a>
|
||||
提交
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div style=" margin: 40px 14px 0; padding: 20px 0 10px; background-color: #f4f5f7;">
|
||||
<h3 style="padding: 5px 0 20px; color: #333;">Sa-Token 官方公众号,及时接收框架更新通知、技术文章</h3>
|
||||
<img class="lazy gzh-qr" data-original="https://oss.dev33.cn/sa-token/lykj-gzh.jpg" style="width: 150px; cursor: pointer;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- ------------ 使用公司 ------------- -->
|
||||
<div>
|
||||
<div class="com-box-f s-width">
|
||||
@@ -312,7 +376,8 @@
|
||||
<a href="javascript:;" title="辽宁薪达网络科技有限公司">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/com/taipingyangcanyin.png">
|
||||
</a>
|
||||
<a href="https://www.pactera.com/?renqun_youhua=2483561&bd_vid=9062916023494825120" target="_blank" title="中电文思海辉">
|
||||
<a href="https://www.pactera.com/?renqun_youhua=2483561&bd_vid=9062916023494825120"
|
||||
target="_blank" title="中电文思海辉">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/com/zhongdianwensi-logo.png">
|
||||
</a>
|
||||
<a href="https://tisiqikeji.com/" target="_blank" title="吉林省体思奇健康科技有限公司">
|
||||
@@ -354,18 +419,28 @@
|
||||
<a href="https://www.zhongyuankeji.cn/" target="_blank" title="山东众远信息科技有限公司">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/com/zhongyuankeji.png">
|
||||
</a>
|
||||
<a href="https://xmnk.cn/" target="_blank" title="希梦耐康网络科技">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/com/ximengnaikang.png">
|
||||
</a>
|
||||
<a href="https://hxp.liuxin.online/" target="_blank" title="沪小漂">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/com/hero.png">
|
||||
</a>
|
||||
<a href="https://www.mall4j.com/" target="_blank" title="广州市蓝海创新科技有限公司">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/com/guangzhoulanhai.png">
|
||||
</a>
|
||||
</div>
|
||||
<div style="height: 10px; clear: both;"></div>
|
||||
<p>
|
||||
(如果您的企业也使用了 Sa-Token,您可以
|
||||
<a href="https://gitee.com/dromara/sa-token/issues/I3EV1M" target="_blank" style="text-decoration: none;">在此</a>
|
||||
<a href="https://gitee.com/dromara/sa-token/issues/I3EV1M" target="_blank"
|
||||
style="text-decoration: none;">在此</a>
|
||||
提交)
|
||||
</p>
|
||||
</div>
|
||||
<div style="height: 60px;"></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- ------------ Dromara 成员项目 ------------- -->
|
||||
<div>
|
||||
<div class="com-box-f s-width">
|
||||
@@ -376,131 +451,208 @@
|
||||
</h2>
|
||||
<div class="com-box com-box-you">
|
||||
<a href="https://gitee.com/dromara/TLog" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/tlog.png" msg="一个轻量级的分布式日志标记追踪神器,10分钟即可接入,自动对日志打标签完成微服务的链路追踪">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/tlog.png"
|
||||
msg="一个轻量级的分布式日志标记追踪神器,10分钟即可接入,自动对日志打标签完成微服务的链路追踪">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/liteFlow" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/liteflow.png" msg="轻量,快速,稳定,可编排的组件式流程引擎">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/liteflow.png"
|
||||
msg="轻量,快速,稳定,可编排的组件式流程引擎">
|
||||
</a>
|
||||
<a href="https://hutool.cn/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/hutool.jpg" msg="🍬小而全的Java工具类库,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/hutool.jpg"
|
||||
msg="??小而全的Java工具类库,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。">
|
||||
</a>
|
||||
<a href="https://sa-token.cc/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/sa-token.png" msg="一个轻量级 java 权限认证框架,让鉴权变得简单、优雅!">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/sa-token.png"
|
||||
msg="一个轻量级 java 权限认证框架,让鉴权变得简单、优雅!">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/hmily" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/hmily.png" msg="高性能一站式分布式事务解决方案。">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/hmily.png"
|
||||
msg="高性能一站式分布式事务解决方案。">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/Raincat" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/raincat.png" msg="强一致性分布式事务解决方案。">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/raincat.png"
|
||||
msg="强一致性分布式事务解决方案。">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/myth" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/myth.png" msg="可靠消息分布式事务解决方案。">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/myth.png"
|
||||
msg="可靠消息分布式事务解决方案。">
|
||||
</a>
|
||||
<a href="https://cubic.jiagoujishu.com/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/cubic.png" msg="一站式问题定位平台,以agent的方式无侵入接入应用,完整集成arthas功能模块,致力于应用级监控,帮助开发人员快速定位问题">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/cubic.png"
|
||||
msg="一站式问题定位平台,以agent的方式无侵入接入应用,完整集成arthas功能模块,致力于应用级监控,帮助开发人员快速定位问题">
|
||||
</a>
|
||||
<a href="https://maxkey.top/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/maxkey.png" msg="业界领先的身份管理和认证产品">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/maxkey.png"
|
||||
msg="业界领先的身份管理和认证产品">
|
||||
</a>
|
||||
<a href="http://forest.dtflyx.com/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/forest-logo.png" msg="Forest能够帮助您使用更简单的方式编写Java的HTTP客户端" nf>
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/forest-logo.png"
|
||||
msg="Forest能够帮助您使用更简单的方式编写Java的HTTP客户端" nf>
|
||||
</a>
|
||||
<a href="https://jpom.top/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/jpom.png" msg="一款简而轻的低侵入式在线构建、自动部署、日常运维、项目监控软件">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/jpom.png"
|
||||
msg="一款简而轻的低侵入式在线构建、自动部署、日常运维、项目监控软件">
|
||||
</a>
|
||||
<a href="https://su.usthe.com/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/sureness.png" msg="面向 REST API 的高性能认证鉴权框架">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/sureness.png"
|
||||
msg="面向 REST API 的高性能认证鉴权框架">
|
||||
</a>
|
||||
<a href="https://easy-es.cn/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/easy-es2.png" msg="🚀傻瓜级ElasticSearch搜索引擎ORM框架">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/easy-es2.png"
|
||||
msg="??傻瓜级ElasticSearch搜索引擎ORM框架">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/northstar" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/northstar_logo.png" msg="Northstar盈富量化交易平台">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/northstar_logo.png"
|
||||
msg="Northstar盈富量化交易平台">
|
||||
</a>
|
||||
<a href="https://hertzbeat.com/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/hertzbeat-brand.svg" msg="易用友好的云监控系统">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/hertzbeat-brand.svg"
|
||||
msg="易用友好的云监控系统">
|
||||
</a>
|
||||
<a href="https://dromara.gitee.io/fast-request/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/fast-request.gif" msg="Idea 版 Postman,为简化调试API而生">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/fast-request.gif"
|
||||
msg="Idea 版 Postman,为简化调试API而生">
|
||||
</a>
|
||||
<a href="https://www.jeesuite.com/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/mendmix.png" msg="开源分布式云原生架构一站式解决方案">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/mendmix.png"
|
||||
msg="开源分布式云原生架构一站式解决方案">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/koalas-rpc" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/koalas-rpc2.png" msg="企业生产级百亿日PV高可用可拓展的RPC框架。">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/koalas-rpc2.png"
|
||||
msg="企业生产级百亿日PV高可用可拓展的RPC框架。">
|
||||
</a>
|
||||
<a href="https://async.sizegang.cn/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/gobrs-async.png" msg="🔥 配置极简功能强大的异步任务动态编排框架">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/gobrs-async.png"
|
||||
msg="?? 配置极简功能强大的异步任务动态编排框架">
|
||||
</a>
|
||||
<a href="https://dynamictp.cn/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/dynamic-tp.png" msg="🔥🔥🔥 基于配置中心的轻量级动态可监控线程池">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/dynamic-tp.png"
|
||||
msg="?????? 基于配置中心的轻量级动态可监控线程池">
|
||||
</a>
|
||||
<a href="https://www.x-easypdf.cn" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/x-easypdf.png" msg="一个用搭积木的方式构建pdf的框架(基于pdfbox)">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/x-easypdf.png"
|
||||
msg="一个用搭积木的方式构建pdf的框架(基于pdfbox)">
|
||||
</a>
|
||||
<a href="http://dromara.gitee.io/image-combiner" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/image-combiner.png" msg="一个专门用于图片合成的工具,没有很复杂的功能,简单实用,却不失强大">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/image-combiner.png"
|
||||
msg="一个专门用于图片合成的工具,没有很复杂的功能,简单实用,却不失强大">
|
||||
</a>
|
||||
<a href="https://www.herodotus.cn/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/dante-cloud2.png" msg="Dante-Cloud 是一款企业级微服务架构和服务能力开发平台。">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/dante-cloud2.png"
|
||||
msg="Dante-Cloud 是一款企业级微服务架构和服务能力开发平台。">
|
||||
</a>
|
||||
<a href="http://www.mtruning.club" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/go-view.png" msg="低代码数据可视化开发平台">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/go-view.png"
|
||||
msg="低代码数据可视化开发平台">
|
||||
</a>
|
||||
<a href="https://tangyh.top/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/lamp-cloud.png" msg="微服务中后台快速开发平台,支持租户(SaaS)模式、非租户模式">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/lamp-cloud.png"
|
||||
msg="微服务中后台快速开发平台,支持租户(SaaS)模式、非租户模式">
|
||||
</a>
|
||||
<a href="https://www.redisfront.com/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/redis-front.png" msg="RedisFront 是一款开源免费的跨平台 Redis 桌面客户端工具, 支持单机模式, 集群模式, 哨兵模式以及 SSH 隧道连接, 可轻松管理Redis缓存数据.">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/redis-front.png"
|
||||
msg="RedisFront 是一款开源免费的跨平台 Redis 桌面客户端工具, 支持单机模式, 集群模式, 哨兵模式以及 SSH 隧道连接, 可轻松管理Redis缓存数据.">
|
||||
</a>
|
||||
<a href="https://www.yuque.com/u34495/mivcfg" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/electron-egg.png" msg="一个入门简单、跨平台、企业级桌面软件开发框架">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/electron-egg.png"
|
||||
msg="一个入门简单、跨平台、企业级桌面软件开发框架">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/open-capacity-platform" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/open-capacity-platform.jpg" msg="简称ocp是基于Spring Cloud的企业级微服务框架(用户权限管理,配置中心管理,应用管理,....)">
|
||||
<img class="lazy"
|
||||
data-original="https://oss.dev33.cn/sa-token/link/open-capacity-platform.jpg"
|
||||
msg="简称ocp是基于Spring Cloud的企业级微服务框架(用户权限管理,配置中心管理,应用管理,....)">
|
||||
</a>
|
||||
<a href="http://easy-trans.fhs-opensource.top/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/easy_trans.png" msg="Easy-Trans 一个注解搞定数据翻译,减少30%SQL代码量">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/easy_trans.png"
|
||||
msg="Easy-Trans 一个注解搞定数据翻译,减少30%SQL代码量">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/neutrino-proxy" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/neutrino-proxy.svg" msg="一款基于 Netty 的、开源的内网穿透神器。">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/neutrino-proxy.svg"
|
||||
msg="一款基于 Netty 的、开源的内网穿透神器。">
|
||||
</a>
|
||||
<a href="https://chatgpt.cn.obiscr.com/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/chatgpt.png" msg="一个支持在 JetBrains 系列 IDE 上运行的 ChatGPT 的插件。">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/chatgpt.png"
|
||||
msg="一个支持在 JetBrains 系列 IDE 上运行的 ChatGPT 的插件。">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/zyplayer-doc" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/zyplayer-doc.png" msg="zyplayer-doc是一款适合团队和个人使用的WIKI文档管理工具,同时还包含数据库文档、Api接口文档。">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/zyplayer-doc.png"
|
||||
msg="zyplayer-doc是一款适合团队和个人使用的WIKI文档管理工具,同时还包含数据库文档、Api接口文档。">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/payment-spring-boot" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/payment-spring-boot.png" msg="最全最好用的微信支付V3 Spring Boot 组件。">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/payment-spring-boot.png"
|
||||
msg="最全最好用的微信支付V3 Spring Boot 组件。">
|
||||
</a>
|
||||
<a href="https://www.j2eefast.com/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/j2eefast.png" msg="J2eeFAST 是一个致力于中小企业 Java EE 企业级快速开发平台,我们永久开源!">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/j2eefast.png"
|
||||
msg="J2eeFAST 是一个致力于中小企业 Java EE 企业级快速开发平台,我们永久开源!">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/data-compare" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/dataCompare.png" msg="数据库比对工具:hive 表数据比对,mysql、Doris 数据比对,实现自动化配置进行数据比对,避免频繁写sql 进行处理,低代码(Low-Code) 平台">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/dataCompare.png"
|
||||
msg="数据库比对工具:hive 表数据比对,mysql、Doris 数据比对,实现自动化配置进行数据比对,避免频繁写sql 进行处理,低代码(Low-Code) 平台">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/open-giteye-api" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/open-giteye-api.svg" msg="giteye.net 是专为开源作者设计的数据图表服务工具类站点,提供了包括 Star 趋势图、贡献者列表、Gitee指数等数据图表服务。">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/open-giteye-api.svg"
|
||||
msg="giteye.net 是专为开源作者设计的数据图表服务工具类站点,提供了包括 Star 趋势图、贡献者列表、Gitee指数等数据图表服务。">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/RuoYi-Vue-Plus" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/RuoYi-Vue-Plus.png" msg="后台管理系统 重写 RuoYi-Vue 所有功能 集成 Sa-Token + Mybatis-Plus + Jackson + Xxl-Job + SpringDoc + Hutool + OSS 定期同步">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/RuoYi-Vue-Plus.png"
|
||||
msg="后台管理系统 重写 RuoYi-Vue 所有功能 集成 Sa-Token + Mybatis-Plus + Jackson + Xxl-Job + SpringDoc + Hutool + OSS 定期同步">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/RuoYi-Cloud-Plus" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/RuoYi-Cloud-Plus.png" msg="微服务管理系统 重写RuoYi-Cloud所有功能 整合 SpringCloudAlibaba Dubbo3.0 Sa-Token Mybatis-Plus MQ OSS ES Xxl-Job Docker 全方位升级 定期同步">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/RuoYi-Cloud-Plus.png"
|
||||
msg="微服务管理系统 重写RuoYi-Cloud所有功能 整合 SpringCloudAlibaba Dubbo3.0 Sa-Token Mybatis-Plus MQ OSS ES Xxl-Job Docker 全方位升级 定期同步">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/stream-query" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/stream-query.png" msg="允许完全摆脱 Mapper 的 mybatis-plus 体验!封装 stream 和 lambda 操作进行数据返回处理。">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/stream-query.png"
|
||||
msg="允许完全摆脱 Mapper 的 mybatis-plus 体验!封装 stream 和 lambda 操作进行数据返回处理。">
|
||||
</a>
|
||||
<a href="https://wind.kim/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/sms4j.png" msg="短信聚合工具,让发送短信变的更简单。">
|
||||
</a>
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/sms4j.png"
|
||||
msg="短信聚合工具,让发送短信变的更简单。">
|
||||
</a>
|
||||
<a href="https://cloudeon.top/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/cloudeon.png" msg="简化kubernetes上大数据集群的运维管理">
|
||||
</a>
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/cloudeon.png"
|
||||
msg="简化kubernetes上大数据集群的运维管理">
|
||||
</a>
|
||||
<a href="https://github.com/dromara/hodor" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/hodor.png"
|
||||
msg="Hodor是一个专注于任务编排和高可用性的分布式任务调度系统。">
|
||||
</a>
|
||||
<a href="http://nsrule.com/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/test-hub.png"
|
||||
msg="流程编排,插件驱动,测试无限可能">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/disjob" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/disjob-2.png"
|
||||
msg="Disjob是一个分布式的任务调度框架">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/binlog4j" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/Binlog4j.png"
|
||||
msg="轻量级 Mysql Binlog 客户端, 提供宕机续读, 高可用集群等特性">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/yft-design" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/yft-design.png"
|
||||
msg="基于 Canvas 的开源版 创客贴 支持导出json,svg, image文件。">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/spring-file-storage" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/file4j.png"
|
||||
msg="在 SpringBoot 中通过简单的方式将文件存储到 本地、阿里云 OSS、腾讯云 COS、七牛云 Kodo等">
|
||||
</a>
|
||||
|
||||
<a href="https://wemq.nicholasld.cn/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/wemq.png"
|
||||
msg="开源、高性能、安全、功能强大的物联网调试和管理解决方案。">
|
||||
</a>
|
||||
<a href="https://gitee.com/dromara/mayfly-go" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/mayfly-go.png"
|
||||
msg="web 版 linux(终端[终端回放] 文件 脚本 进程 计划任务)、数据库(mysql postgres)、redis(单机 哨兵 集群)、mongo 统一管理操作平台">
|
||||
</a>
|
||||
|
||||
<a href="https://dromara.org/zh/projects/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/dromara.png" msg="让每一位开源爱好者,体会到开源的快乐。">
|
||||
</a>
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/dromara.png"
|
||||
msg="让每一位开源爱好者,体会到开源的快乐。">
|
||||
</a>
|
||||
</div>
|
||||
<div style="height: 10px; clear: both;"></div>
|
||||
<p>
|
||||
@@ -508,12 +660,13 @@
|
||||
</p>
|
||||
<div style=" margin: 40px 14px 0; padding: 20px 0 10px; background-color: #f4f5f7;">
|
||||
<h3 style="padding: 0px 0 10px; ">Dromara 知识星球</h3>
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/dromara-xingqiu--sa-token.jpg" style="width: 300px;">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/dromara-xingqiu--sa-token.jpg"
|
||||
style="width: 300px;">
|
||||
</div>
|
||||
</div>
|
||||
<div style="height: 30px;"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- ------------ 友情链接 ------------- -->
|
||||
<div>
|
||||
<div class="com-box-f s-width">
|
||||
@@ -522,42 +675,57 @@
|
||||
<h2 class="s-title">友情链接</h2>
|
||||
<div class="com-box com-box-you">
|
||||
<a href="https://okhttps.ejlchina.com/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/okhttps.png" msg="如艺术一般优雅,像 1、2、3 一样简单,前后端通用,轻量却强大的 HTTP 客户端(同时支持 WebSocket 以及 Stomp 协议)">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/okhttps.png"
|
||||
msg="如艺术一般优雅,像 1、2、3 一样简单,前后端通用,轻量却强大的 HTTP 客户端(同时支持 WebSocket 以及 Stomp 协议)">
|
||||
</a>
|
||||
<a href="https://searcher.ejlchina.com/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/bean-searcher.png" msg="轻量级关系数据库条件检索引擎,使一行代码实现复杂列表检索成为可能!">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/bean-searcher.png"
|
||||
msg="轻量级关系数据库条件检索引擎,使一行代码实现复杂列表检索成为可能!">
|
||||
</a>
|
||||
<a href="https://xiaonuo.vip/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/xiaonuo2.png" msg="通用型后台权限管理框架,紧随潮流、开箱即用, 同时拥有Vue、Layui、SpringCloud三个版本">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/xiaonuo2.png"
|
||||
msg="通用型后台权限管理框架,紧随潮流、开箱即用, 同时拥有Vue、Layui、SpringCloud三个版本">
|
||||
</a>
|
||||
<a href="http://www.pearadmin.com/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/pear-admin.png" msg="致 力 于 让 Web 开 发 变 得 简 单 优 雅">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/pear-admin.png"
|
||||
msg="致 力 于 让 Web 开 发 变 得 简 单 优 雅">
|
||||
</a>
|
||||
<a href="http://www.layui-vue.com/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/layui-vue.png" msg="layui - vue(谐音:类 UI) 是 一 套 Vue 3.0 的 桌 面 端 组 件 库.">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/layui-vue.png"
|
||||
msg="layui - vue(谐音:类 UI) 是 一 套 Vue 3.0 的 桌 面 端 组 件 库.">
|
||||
</a>
|
||||
<a href="https://shenyu.apache.org/zh/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/shenyu.svg" msg="一个异步的,高性能的,跨语言的,响应式的 API 网关。">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/shenyu.svg"
|
||||
msg="一个异步的,高性能的,跨语言的,响应式的 API 网关。">
|
||||
</a>
|
||||
<a href="https://dwz.cn/L9hCwepg" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/com/yungouos.png" msg="官方直连支付系统解决方案,支持个人、个体户、企业全渠道签约。">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/com/yungouos.png"
|
||||
msg="官方直连支付系统解决方案,支持个人、个体户、企业全渠道签约。">
|
||||
</a>
|
||||
<a href="https://hippo4j.cn/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/hippo4j.jpg" msg="强大的动态线程池框架,附带监控报警功能,支持 Tomcat、Jetty、Undertow、RocketMQ、Dubbo、RabbitMQ、Hystrix 消费线程池">
|
||||
</a>
|
||||
<a href="http://solon.noear.org/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/solon.png" msg="一个更现代感的应用开发框架:更快、更小、更自由。">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/hippo4j.jpg"
|
||||
msg="强大的动态线程池框架,附带监控报警功能,支持 Tomcat、Jetty、Undertow、RocketMQ、Dubbo、RabbitMQ、Hystrix 消费线程池">
|
||||
</a>
|
||||
<a href="https://gitee.com/gz-yami/mall4j" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/mall4j.png" msg="一个基于Spring Boot 3 JDK17的商城系统。">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/mall4j.png"
|
||||
msg="一个基于Spring Boot 3 JDK17的商城系统。">
|
||||
</a>
|
||||
<a href="http://solon.noear.org/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/solon.png"
|
||||
msg="一个更现代感的应用开发框架:更快、更小、更自由。">
|
||||
</a>
|
||||
<a href="https://baomidou.com/" target="_blank">
|
||||
<img class="lazy" data-original="https://oss.dev33.cn/sa-token/link/mybatis-plus.png"
|
||||
style="max-width: 110%;"
|
||||
msg="MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。">
|
||||
</a>
|
||||
</div>
|
||||
<div style="height: 10px; clear: both;"></div>
|
||||
</div>
|
||||
<div style="height: 60px;"></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- ------------ 底部 连接 ------------- -->
|
||||
<div id="footer">
|
||||
<div id="s-footer" class="mao-link"></div>
|
||||
@@ -566,7 +734,8 @@
|
||||
<h3>特别鸣谢</h3>
|
||||
<ul class="list-unstyle">
|
||||
<li><a href="https://dromara.org/zh/projects/" target="_blank">Dromara社区</a></li>
|
||||
<li><a href="https://gitee.com/Apache-ShenYu/incubator-shenyu" target="_blank">ShenYu 网关</a></li>
|
||||
<li><a href="https://gitee.com/Apache-ShenYu/incubator-shenyu" target="_blank">ShenYu 网关</a>
|
||||
</li>
|
||||
<li><a href="https://gitee.com/dromara/TLog" target="_blank">TLog 分布式日志</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -597,30 +766,35 @@
|
||||
<div class="ss-box">
|
||||
<h3 class="last" style="text-align: left; float: none; padding-left: 0px;">Sa-Token 公众号</h3>
|
||||
<div class="media-img padding-small-top" style="text-align: left;">
|
||||
<img class="dro-qr" src="https://oss.dev33.cn/sa-token/lykj-gzh.jpg" width="100" height="100" />
|
||||
<img class="dro-qr" src="https://oss.dev33.cn/sa-token/lykj-gzh.jpg" width="100"
|
||||
height="100" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- -------------- 底部 版权 -------------- -->
|
||||
<div>
|
||||
<meta charset="UTF-8">
|
||||
<style type="text/css">
|
||||
|
||||
|
||||
</style>
|
||||
<div class="foot-box" id="foot">
|
||||
<div class="s-width" style="text-align: center;">
|
||||
Copyright ©2022 Sa-Token java权限认证 | sa-token.cc | <a href="https://beian.miit.gov.cn/" target="_blank">鲁ICP备18046274号-4</a>
|
||||
Copyright ©2022 Sa-Token java权限认证 | sa-token.cc | <a href="https://beian.miit.gov.cn/"
|
||||
target="_blank">鲁ICP备18046274号-4</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- UI逐渐显现 -->
|
||||
<style type="text/css">
|
||||
body{opacity: 0.01; transition: opacity 0.5s;}
|
||||
body {
|
||||
opacity: 0.01;
|
||||
transition: opacity 0.5s;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
setTimeout(function() {
|
||||
@@ -642,44 +816,43 @@
|
||||
s.parentNode.insertBefore(bp, s);
|
||||
})();
|
||||
</script>
|
||||
<!-- 友盟统计 -->
|
||||
<div style="height: 0px; overflow: hidden;">
|
||||
<script type="text/javascript" src="https://s4.cnzz.com/z_stat.php?id=1279646043&web_id=1279646043"></script>
|
||||
</div>
|
||||
<!-- 百度统计 -->
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?35ad501304eae758ac6139a22a9830f5";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
<!-- 悬浮效果 -->
|
||||
<script src="static/jquery.min.js"></script>
|
||||
<script src="static/layer-v3.1.1/layer.js"></script>
|
||||
<script type="text/javascript">
|
||||
// 鼠标悬浮在友情链接时,提示信息
|
||||
$(".com-box-you a img").hover(function(){
|
||||
var msg = $(this).attr("msg") ;
|
||||
if(msg) {
|
||||
window.msgLayer = layer.tips(msg, $(this), {tips: 1, time: 0});
|
||||
$(".com-box-you a img").hover(function() {
|
||||
var msg = $(this).attr("msg");
|
||||
if (msg) {
|
||||
window.msgLayer = layer.tips(msg, $(this), {
|
||||
tips: 1,
|
||||
time: 0
|
||||
});
|
||||
}
|
||||
},function(){
|
||||
}, function() {
|
||||
var index = window.msgLayer;
|
||||
setTimeout(function() {
|
||||
layer.close(index);
|
||||
}, 1000);
|
||||
});
|
||||
// 点击二维码放大
|
||||
$('.wx-qr,.dro-qr').click(function() {
|
||||
$('.wx-qr,.dro-qr,.gzh-qr').click(function() {
|
||||
var w = '300px';
|
||||
var h = 'auto';
|
||||
var content = '<div style="height: 100%; overflow: hidden !important;">' +
|
||||
'<img src="' + this.src + ' " style="width: 100%; height: 100%;" />' +
|
||||
'</div>';
|
||||
var content = '<div style="height: 100%; overflow: hidden !important;">' +
|
||||
'<img src="' + this.src + ' " style="width: 100%; height: 100%;" />' +
|
||||
'</div>';
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: false,
|
||||
@@ -689,12 +862,14 @@
|
||||
content: content
|
||||
});
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<!-- 初始化轮播图 -->
|
||||
<script src="static/swiper/swiper-bundle.min.js"></script>
|
||||
<script src="static/swiper/index-swiper.js"></script>
|
||||
|
||||
<!-- 修改背景颜色 -->
|
||||
<script>
|
||||
|
||||
// 绑定修改背景色的按钮事件
|
||||
$('.theme-box span').click(function() {
|
||||
let bgColor = this.style.backgroundColor;
|
||||
@@ -703,84 +878,83 @@
|
||||
})
|
||||
// 读取上次记录
|
||||
let bgColor = localStorage.getItem('bg-color-value');
|
||||
if(bgColor) {
|
||||
if (bgColor) {
|
||||
setBg(bgColor);
|
||||
}
|
||||
|
||||
|
||||
// 设置背景颜色
|
||||
function setBg(bgColor) {
|
||||
console.log('---- 背景颜色设定为:', bgColor);
|
||||
|
||||
|
||||
// -------- 设置 body 背景
|
||||
document.body.style.backgroundColor = bgColor;
|
||||
|
||||
|
||||
// -------- 设置 header 头背景
|
||||
// 如果是 16 进制,转 rgba
|
||||
if(bgColor.indexOf('#') == 0) {
|
||||
if (bgColor.indexOf('#') == 0) {
|
||||
bgColor = hexToRgba(bgColor, 0.97);
|
||||
}
|
||||
// 如果是 rgb,转 rgba
|
||||
else if(bgColor.match(/\,/g).length == 2) {
|
||||
else if (bgColor.match(/\,/g).length == 2) {
|
||||
bgColor = bgColor.replace(')', ' ,0.97)');
|
||||
}
|
||||
|
||||
|
||||
document.querySelector('.doc-header').style.backgroundColor = bgColor;
|
||||
}
|
||||
|
||||
|
||||
// 16进制 转 rgba
|
||||
function hexToRgba(str, a){
|
||||
function hexToRgba(str, a) {
|
||||
a = a || 1;
|
||||
|
||||
|
||||
var reg = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/
|
||||
if(!reg.test(str)){return;}
|
||||
let newStr = (str.toLowerCase()).replace(/\#/g,'')
|
||||
if (!reg.test(str)) {
|
||||
return;
|
||||
}
|
||||
let newStr = (str.toLowerCase()).replace(/\#/g, '')
|
||||
let len = newStr.length;
|
||||
if(len == 3){
|
||||
if (len == 3) {
|
||||
let t = ''
|
||||
for(var i=0;i<len;i++){
|
||||
t += newStr.slice(i,i+1).concat(newStr.slice(i,i+1))
|
||||
for (var i = 0; i < len; i++) {
|
||||
t += newStr.slice(i, i + 1).concat(newStr.slice(i, i + 1))
|
||||
}
|
||||
newStr = t
|
||||
}
|
||||
let arr = []; //将字符串分隔,两个两个的分隔
|
||||
for(var i =0;i<6;i=i+2){
|
||||
let s = newStr.slice(i,i+2)
|
||||
for (var i = 0; i < 6; i = i + 2) {
|
||||
let s = newStr.slice(i, i + 2)
|
||||
arr.push(parseInt("0x" + s))
|
||||
}
|
||||
return 'rgb(' + arr.join(",") + ', ' + a + ')';
|
||||
return 'rgb(' + arr.join(",") + ', ' + a + ')';
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<!-- 图片懒加载 -->
|
||||
<script src="static/jquery.lazyload-1.9.3.js"></script>
|
||||
<script>
|
||||
$(function() {
|
||||
$("img.lazy").lazyload({
|
||||
effect: "fadeIn", // 动画,show=显示,fadeIn=淡入,slideDown=下拉
|
||||
effectspeed: 1200, // 动画持续时间
|
||||
effect: "fadeIn", // 动画,show=显示,fadeIn=淡入,slideDown=下拉
|
||||
effectspeed: 1200, // 动画持续时间
|
||||
skip_invisible: true, // 不加载隐藏的图像
|
||||
// threshold: -180, // 提前加载:距离屏幕多少px时就显示出来
|
||||
// event: 'click', // 事件触发时才加载,scroll=滑动,click=点击,mouseover=鼠标划过,sporty=运动的
|
||||
// 未加载时的占位图,此为3x3透明小图片
|
||||
placeholder:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAYAAABWKLW/AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAhdEVYdENyZWF0aW9uIFRpbWUAMjAyMTowMToyMiAyMjoxNDoxM63SwyUAAAANSURBVBhXYyAGMDAAAAAnAAF2ypRxAAAAAElFTkSuQmCC",
|
||||
load: function(){
|
||||
placeholder: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAYAAABWKLW/AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAhdEVYdENyZWF0aW9uIFRpbWUAMjAyMTowMToyMiAyMjoxNDoxM63SwyUAAAANSURBVBhXYyAGMDAAAAAnAAF2ypRxAAAAAElFTkSuQmCC",
|
||||
load: function() {
|
||||
console.log('lazy img: ' + this.src);
|
||||
}
|
||||
});
|
||||
})
|
||||
// $(window).bind("load", function() {
|
||||
// // var timeout = setTimeout(function() {$("img.lazy").trigger("sporty")}, 5000);
|
||||
// });
|
||||
</script>
|
||||
|
||||
|
||||
<!-- 预览版提示 -->
|
||||
<script type="text/javascript">
|
||||
// 预览版提示
|
||||
if(location.host === 'rc.sa-token.cc') {
|
||||
const newTips = '<b>当前文档为RC预览版文档,仅做学习测试使用,正式项目请使用正式版:<a href="https://sa-token.cc/" target="_blank">https://sa-token.cc/</a></b>';
|
||||
if (location.host === 'rc.sa-token.cc') {
|
||||
const newTips =
|
||||
'<b>当前文档为RC预览版文档,仅做学习测试使用,正式项目请使用正式版:<a href="https://sa-token.cc/" target="_blank">https://sa-token.cc/</a></b>';
|
||||
layer.alert(newTips);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
<!---------------------------- tabs:start ------------------------------>
|
||||
<!-------- tab:Maven 方式 -------->
|
||||
注:如果你使用的是 `SpringBoot 3.x`,只需要将 `sa-token-reactor-spring-boot-starter` 修改为 `sa-token-reactor-spring-boot3-starter` 即可。
|
||||
``` xml
|
||||
<!-- Sa-Token 权限认证(Reactor响应式集成), 在线文档:https://sa-token.cc -->
|
||||
<dependency>
|
||||
@@ -36,6 +37,7 @@
|
||||
</dependency>
|
||||
```
|
||||
<!-------- tab:Gradle 方式 -------->
|
||||
注:如果你使用的是 `SpringBoot 3.x`,只需要将 `sa-token-reactor-spring-boot-starter` 修改为 `sa-token-reactor-spring-boot3-starter` 即可。
|
||||
``` gradle
|
||||
// Sa-Token 权限认证(Reactor响应式集成),在线文档:https://sa-token.cc
|
||||
implementation 'cn.dev33:sa-token-reactor-spring-boot-starter:${sa.top.version}'
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
<!---------------------------- tabs:start ---------------------------->
|
||||
<!-------- tab:Maven 方式 -------->
|
||||
注:如果你使用的是 `SpringBoot 3.x`,只需要将 `sa-token-spring-boot-starter` 修改为 `sa-token-spring-boot3-starter` 即可。
|
||||
``` xml
|
||||
<!-- Sa-Token 权限认证,在线文档:https://sa-token.cc -->
|
||||
<dependency>
|
||||
@@ -20,6 +21,7 @@
|
||||
</dependency>
|
||||
```
|
||||
<!-------- tab:Gradle 方式 -------->
|
||||
注:如果你使用的是 `SpringBoot 3.x`,只需要将 `sa-token-spring-boot-starter` 修改为 `sa-token-spring-boot3-starter` 即可。
|
||||
``` gradle
|
||||
// Sa-Token 权限认证,在线文档:https://sa-token.cc
|
||||
implementation 'cn.dev33:sa-token-spring-boot-starter:${sa.top.version}'
|
||||
@@ -28,6 +30,7 @@ implementation 'cn.dev33:sa-token-spring-boot-starter:${sa.top.version}'
|
||||
|
||||
<!---------------------------- tabs:start ------------------------------>
|
||||
<!-------- tab:Maven 方式 -------->
|
||||
注:如果你使用的是 `SpringBoot 3.x`,只需要将 `sa-token-reactor-spring-boot-starter` 修改为 `sa-token-reactor-spring-boot3-starter` 即可。
|
||||
``` xml
|
||||
<!-- Sa-Token 权限认证(Reactor响应式集成),在线文档:https://sa-token.cc -->
|
||||
<dependency>
|
||||
@@ -37,6 +40,7 @@ implementation 'cn.dev33:sa-token-spring-boot-starter:${sa.top.version}'
|
||||
</dependency>
|
||||
```
|
||||
<!-------- tab:Gradle 方式 -------->
|
||||
注:如果你使用的是 `SpringBoot 3.x`,只需要将 `sa-token-reactor-spring-boot-starter` 修改为 `sa-token-reactor-spring-boot3-starter` 即可。
|
||||
``` gradle
|
||||
// Sa-Token 权限认证(Reactor响应式集成),在线文档:https://sa-token.cc
|
||||
implementation 'cn.dev33:sa-token-reactor-spring-boot-starter:${sa.top.version}'
|
||||
@@ -50,7 +54,7 @@ implementation 'cn.dev33:sa-token-reactor-spring-boot-starter:${sa.top.version}'
|
||||
因为这个SpringMVC是基于Servlet模型的,在这里我们需要引入的是`sa-token-spring-boot-starter`
|
||||
|
||||
对于网关服务,大体来讲分为两种:
|
||||
- 一种是基于Servlet模型的,如:Zuul,我们需要引入的是:`sa-token-spring-boot-starter`,详细戳:[在SpringBoot环境集成](/start/example)
|
||||
- 一种是基于Servlet模型的,如:Zuul,我们需要引入的是:`sa-token-spring-boot-starter`,详细戳:[在SpringBoot环境集成](/start/example);理论上`Zuul`并不支持`Spring Boot3`
|
||||
- 一种是基于Reactor模型的,如:SpringCloud Gateway、ShenYu 等等,我们需要引入的是:`sa-token-reactor-spring-boot-starter`,**并且注册全局过滤器!**,详细戳:[在WebFlux环境集成](/start/webflux-example)
|
||||
|
||||
注:切不可直接在一个项目里同时引入这两个依赖,否则会造成项目无法启动
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
1. 物理隔离:子服务部署在指定的内网环境中,只有网关对外网开放
|
||||
2. 逻辑隔离:子服务与网关同时暴露在外网,但是子服务会有一个权限拦截层保证只接受网关发送来的请求,绕过网关直接访问子服务会被提示:无效请求
|
||||
|
||||
这种鉴权需求牵扯到两个环节:**`网关转发鉴权`**、**`服务内部调用鉴权`**
|
||||
这种鉴权需求牵扯到两个环节: **`网关转发鉴权`** 、 **`服务间内部调用鉴权`**
|
||||
|
||||
Sa-Token提供两种解决方案:
|
||||
1. 使用 OAuth2.0 模式的凭证式,将 Client-Token 用作各个服务的身份凭证进行权限校验
|
||||
@@ -25,6 +25,7 @@ Sa-Token提供两种解决方案:
|
||||
在网关处引入的依赖为(此处以 SpringCloud Gateway 为例):
|
||||
<!---------------------------- tabs:start ------------------------------>
|
||||
<!-------- tab:Maven 方式 -------->
|
||||
注:如果你使用的是 `SpringBoot 3.x`,只需要将 `sa-token-reactor-spring-boot-starter` 修改为 `sa-token-reactor-spring-boot3-starter` 即可。
|
||||
``` xml
|
||||
<!-- Sa-Token 权限认证(Reactor响应式集成), 在线文档:https://sa-token.cc -->
|
||||
<dependency>
|
||||
@@ -45,6 +46,7 @@ Sa-Token提供两种解决方案:
|
||||
</dependency>
|
||||
```
|
||||
<!-------- tab:Gradle 方式 -------->
|
||||
注:如果你使用的是 `SpringBoot 3.x`,只需要将 `sa-token-reactor-spring-boot-starter` 修改为 `sa-token-reactor-spring-boot3-starter` 即可。
|
||||
``` gradle
|
||||
// Sa-Token 权限认证(Reactor响应式集成),在线文档:https://sa-token.cc
|
||||
implementation 'cn.dev33:sa-token-reactor-spring-boot-starter:${sa.top.version}'
|
||||
@@ -55,9 +57,10 @@ implementation 'org.apache.commons:commons-pool2'
|
||||
```
|
||||
<!---------------------------- tabs:end ------------------------------>
|
||||
|
||||
在子服务引入的依赖为:
|
||||
在下游子服务引入的依赖为:
|
||||
<!---------------------------- tabs:start ------------------------------>
|
||||
<!-------- tab:Maven 方式 -------->
|
||||
注:如果你使用的是 `SpringBoot 3.x`,只需要将 `sa-token-spring-boot-starter` 修改为 `sa-token-spring-boot3-starter` 即可。
|
||||
``` xml
|
||||
<!-- Sa-Token 权限认证, 在线文档:https://sa-token.cc -->
|
||||
<dependency>
|
||||
@@ -78,6 +81,7 @@ implementation 'org.apache.commons:commons-pool2'
|
||||
</dependency>
|
||||
```
|
||||
<!-------- tab:Gradle 方式 -------->
|
||||
注:如果你使用的是 `SpringBoot 3.x`,只需要将 `sa-token-spring-boot-starter` 修改为 `sa-token-spring-boot3-starter` 即可。
|
||||
``` gradle
|
||||
// Sa-Token 权限认证,在线文档:https://sa-token.cc
|
||||
implementation 'cn.dev33:sa-token-spring-boot-starter:${sa.top.version}'
|
||||
@@ -146,7 +150,7 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
||||
> 如果通过网关转发,可以正常访问,直接访问子服务会提示:`无效Same-Token:xxx`
|
||||
|
||||
|
||||
### 三、服务内部调用鉴权
|
||||
### 三、服务间内部调用鉴权
|
||||
|
||||
有时候我们需要在一个服务调用另一个服务的接口,这也是需要添加`Same-Token`作为身份凭证的
|
||||
|
||||
@@ -163,6 +167,9 @@ public class FeignInterceptor implements RequestInterceptor {
|
||||
@Override
|
||||
public void apply(RequestTemplate requestTemplate) {
|
||||
requestTemplate.header(SaSameUtil.SAME_TOKEN, SaSameUtil.getToken());
|
||||
|
||||
// 如果希望被调用方有会话状态,此处就还需要将 satoken 添加到请求头中
|
||||
// requestTemplate.header(StpUtil.getTokenName(), StpUtil.getTokenValue());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
---
|
||||
|
||||
- [[ CSDN ] 【Sa-Token】9、Sa-Token实现在线用户管理功能](https://blog.csdn.net/qq_40065776/article/details/132180932) (2023-08-09)
|
||||
|
||||
- [[ CSDN ] 【RuoYi-Vue-Plus】学习笔记 31 - Sa-Token(五)登录验证拦截器之 Token 有效期及其续签(Sa-Token 源码)](https://blog.csdn.net/Michelle_Zhong/article/details/126071871) (2022-07-30)
|
||||
|
||||
- [[ CSDN ] 【RuoYi-Vue-Plus】学习笔记 29 - Sa-Token(四)V1.30.0 登录流程分析(Sa-Token 源码)](https://blog.csdn.net/Michelle_Zhong/article/details/125659797) (2022-07-07)
|
||||
|
||||
@@ -58,7 +58,8 @@ Sa-Token 的部分 API 只能在 Web 上下文中才能调用,例如:`StpUti
|
||||
- 什么?你说你两个都引入了?那你的项目能启动成功吗?
|
||||
4. 如果是 WebFlux 环境而且正确引入了依赖,依然报错,**请检查是否注册了 SaReactorFilter 全局过滤器,在 WebFlux 下这一步是必须的**,具体还是请参考上面的 [ 在WebFlux环境集成 ] 章节。
|
||||
5. 需要仔细注意,如果你使用的是 Springboot3.x 版本,就不要错误的引入 `sa-token-spring-boot-starter`,需要引入的是 `sa-token-spring-boot3-starter`,不然就会导致框架报错。
|
||||
6. 如果以上步骤排除无误后依然报错,请直接提 issue 或者加入QQ群求助。
|
||||
6. 如果你的项目开启了全局懒加载(spring.main.lazy-initialization=true)后,能启动项目,但是访问接口报异常,请直接参考:[Q:开启了全局懒加载后,能启动项目,但是访问接口报未能获取有效的上下文处理器](/more/common-questions?id=q:开启了全局懒加载后,能启动项目,但是访问接口报未能获取有效的上下文处理器)
|
||||
7. 如果以上步骤排除无误后依然报错,请直接提 issue 或者加入QQ群求助。
|
||||
|
||||
### Q:报错:NotLoginException:xxx
|
||||
|
||||
@@ -71,6 +72,7 @@ Sa-Token 的部分 API 只能在 Web 上下文中才能调用,例如:`StpUti
|
||||
- 可能4:前端提交了 Token,但是 Token前缀 不对,可参考:[自定义 Token 前缀](/up/token-prefix)
|
||||
- 可能5:你的项目属于前后端分离架构,此时浏览器默认不自动提交 Cookie,参考:[前后端分离](/up/not-cookie)
|
||||
- 可能6:你使用了 Nginx 反向代理,而且配置了 自定义Token名称,而且自定义的名称还带有下划线(比如 shop_token),而且还是你的项目还是从 Header头提交Token的,此时 Nginx 默认会吞掉你的下划线参数,可参考:[nginx做转发时,带下划线的header参数丢失](https://blog.csdn.net/zfw_666666/article/details/124420828)
|
||||
- 可能7:可能是跨域了,导致前端提交不上 token,看看前端浏览器有没有跨域的报错。
|
||||
|
||||
**如果是:Token无效:6ad93254-b286-4ec9-9997-4430b0341ca0**
|
||||
- 可能1:前端提交的 token 是乱填的,或者从别的项目拷过来的,或者多个项目一起开发时彼此的 Token 串项目了。
|
||||
@@ -301,6 +303,16 @@ public class SaTokenApplication {
|
||||
|
||||
|
||||
|
||||
### Q:我把 token 有效期设置为 30 天,但是总感觉不到 30 天的时候 token 就无效了,怎么回事?
|
||||
- 可能1:你没有为 sa-token 集成 Redis,框架默认将会话数据保存在内存中,项目重启后数据会消失。
|
||||
- 可能2:你为 sa-token 集成了 Redis,但是 Redis 重启了,导致会话消失。
|
||||
- 可能3:你配置了 `is-concurrent=false`,不允许同一账号多端登录,有别人登录了这个账号把你顶下去了。
|
||||
- 可能4:你配置了 `is-concurrent=true`,但是`is-share=false`,同一账号每次登录产生不同的 token,默认最高可以同时登录12个客户端,超过将自动注销最原先的会话。
|
||||
- 可能5:你的这个账号,别人也登录了,别人调用了注销方法,把你这边的也注销了。`StpUtil.logout()` 为单 token 注销,`StpUtil.logout(10001)` 为账号所有 token 注销。
|
||||
- 可能6:你虽然 `sa-token.timeout` 配置了 30 天,但是 `sa-token.active-timeout` 配置了较短的值,超过这个时间无操作,token 就过期了。
|
||||
- 可能7:你换了浏览器,或者换了电脑,或者清空了浏览器最近缓存记录,自然而然需要重新登录。
|
||||
- 可能8:你中途改了项目配置,比如改了 `sa-token.token-name` 配置项的值,会导致会话保存的 key 发生改变,效果等同于手动清空了 Redis 数据,需要重新登录。
|
||||
|
||||
|
||||
|
||||
### Q:有时候我不加 Token 也可以通过鉴权,请问是怎么回事?
|
||||
@@ -438,6 +450,80 @@ spring.mvc.throw-exception-if-no-handler-found=true
|
||||
|
||||
|
||||
|
||||
### Q:开启了全局懒加载后,能启动项目,但是访问接口报“未能获取有效的上下文处理器”
|
||||
开启了全局懒加载后,能启动项目,但是访问接口报异常 `InvalidContextException`: 未能获取有效的上下文处理器, 配置如下:
|
||||
``` yaml
|
||||
spring:
|
||||
main:
|
||||
lazy-initialization: true
|
||||
```
|
||||
原因是 Sa-Token 自动配置入口类 SaBeanInject 被延迟加载了,只需要手动指定懒加载排除掉 SaBeanInject 就可以了,实现代码如下:
|
||||
``` java
|
||||
@Configuration
|
||||
class MyConfiguration {
|
||||
@Bean
|
||||
LazyInitializationExcludeFilter integrationLazyInitExcludeFilter() {
|
||||
return LazyInitializationExcludeFilter.forBeanTypes(SaBeanInject.class);
|
||||
}
|
||||
}
|
||||
```
|
||||
[经验来源](https://gitee.com/dromara/sa-token/issues/I7EXIU)
|
||||
|
||||
|
||||
### Q:SpringBoot 3.x 路由拦截鉴权报错:No more pattern data allowed after {*...} or ** pattern element
|
||||
|
||||
|
||||
报错原因:SpringBoot3.x 版本默认将路由匹配机制由 `ant_path_matcher` 改为了 `path_pattern_parser` 模式,
|
||||
而此模式有一个规则,就是写路由匹配符的时候,不允许 `**` 之后再出现内容。例如:`/admin/**/info` 就是不允许的。
|
||||
|
||||
如果你的项目报了这个错,说明你写的路由匹配符出现了上述问题,有三种解决方案:
|
||||
1. 等待 SpringMVC 官方增强 `path_pattern_parser` 模式能力,使之可以支持 `**` 之后再出现内容。
|
||||
2. 在写路由匹配规则时,避免使 `**` 之后再出现内容。
|
||||
3. 将项目的路由匹配机制改为 `ant_path_matcher`。
|
||||
|
||||
先改项目的:
|
||||
``` yml
|
||||
spring:
|
||||
mvc:
|
||||
pathmatch:
|
||||
matching-strategy: ant_path_matcher
|
||||
```
|
||||
|
||||
再改 Sa-Token 的:
|
||||
``` java
|
||||
/**
|
||||
* 自定义 SaTokenContext 实现类,重写 matchPath 方法,切换为 ant_path_matcher 模式,使之可以支持 `**` 之后再出现内容
|
||||
*/
|
||||
@Primary
|
||||
@Component
|
||||
public class SaTokenContextByPatternsRequestCondition extends SaTokenContextForSpringInJakartaServlet {
|
||||
|
||||
@Override
|
||||
public boolean matchPath(String pattern, String path) {
|
||||
return SaPatternsRequestConditionHolder.match(pattern, path);
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- ---------------------------- 常见疑问 ----------------------------- -->
|
||||
|
||||
@@ -592,6 +678,39 @@ So:从鉴权粒度的角度来看,需要针对一个模块鉴权的时候,
|
||||
所以只能统一抛出-2,这个行为也和具体使用的 SaTokenDao 有关联,例如集成 sa-token-jwt 插件后,框架就能分辨出来是 token 过期了,抛出-3。
|
||||
|
||||
|
||||
### Q:Sa-Token 是否提供类似 RefreshToken 的概念,与 AccessToken 相互配合刷新令牌鉴权。
|
||||
关于长短 token,Sa-Token 没有提供直接的 API 支持,但是你可以利用 “临时 token 认证模块” 轻易的达到这一点:
|
||||
|
||||
1. 把 `sa-token.timeout` 的值配置小一点,然后把 `StpUtil.login(10001)` 生成的 token 作为短 token ,用来鉴权。
|
||||
2. 用 “临时 token 认证模块” 生成长 token, `String refreshToken = SaTempUtil.createToken(10001, 2592000);`。
|
||||
3. 把这两个 token 一起返回到前端。
|
||||
4. 你再开个接口,可以让前端通过长 token,刷新短 token,参考代码:
|
||||
|
||||
``` java
|
||||
@RequestMapping("/refreshToken")
|
||||
public SaResult refreshToken(String refreshToken) {
|
||||
// 1、验证
|
||||
Object userId = SaTempUtil.parseToken(refreshToken);
|
||||
if(userId == null) {
|
||||
return SaResult.error("无效 refreshToken");
|
||||
}
|
||||
|
||||
// 2、为其生成新的短 token
|
||||
String accessToken = StpUtil.createLoginSession(userId);
|
||||
|
||||
// 3、返回
|
||||
return SaResult.data(accessToken);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Q:怎么改变请求返回的 http 状态码?
|
||||
``` java
|
||||
SaHolder.getResponse().setStatus(401)
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Q:还是有不明白到的地方?
|
||||
请在`gitee` 、 `github` 提交 `issues`,或者加入qq群交流,[群链接](/more/join-group)
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# 加入讨论群
|
||||
|
||||
加入 Sa-Token 专属讨论群,与众多大佬一起努力 (huá shǔi) 成长 (mō yú)。
|
||||
加入 Sa-Token 专属讨论群,与众多大佬一起努力 (huá shuǐ) 成长 (mō yú)。
|
||||
|
||||
---
|
||||
|
||||
### 1、加入QQ交流群
|
||||
|
||||

|
||||

|
||||
|
||||
QQ交流群:707350988 [点击加入](https://jq.qq.com/?_wv=1027&k=tqbzHT2D)
|
||||
QQ交流群:837325627 [点击加入](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=98NOhX0Q3a2hcv3eURcnYMBuZUZrlHUH&authKey=td3pmX3BnYNr%2FCRkEDwE5FgGARk29D9HAMwL0bAfK7tqN8XN93jccnEanyZl18mM&noverify=0&group_code=837325627)
|
||||
|
||||
### 2、加入微信交流群:
|
||||
|
||||
|
||||
+34
-11
@@ -1,13 +1,15 @@
|
||||
# 使用 Sa-Token 的开源项目
|
||||
|
||||
|
||||
> 集成 Sa-Token 的开源案例收集,取自 [Awesome-Sa-Token](https://gitee.com/sa-token/awesome-sa-token),定期同步。
|
||||
> 集成 Sa-Token 的开源案例收集,取自 [Awesome-Sa-Token](https://gitee.com/sa-tokens/awesome-sa-token),定期同步。
|
||||
|
||||
---
|
||||
|
||||
|
||||
### 后台管理
|
||||
|
||||
- [[ srppms ]](https://gitee.com/cai-bin00/srppms):基于SpringBoot+Vue+sa-token前后端分离的科研项目管理平台。
|
||||
|
||||
- [[ twelvet-fast ]](https://gitee.com/twelvet/twelvet-fast):基于Spring Boot 3 JDK17的单体服务极速开发管理平台脚手架,先行体验最新技术栈。
|
||||
|
||||
- [[ Sa-Plus ]](https://gitee.com/click33/sa-plus):一个基于 SpringBoot 架构的快速开发框架,内置代码生成器。
|
||||
@@ -58,6 +60,12 @@
|
||||
|
||||
- [[ springboot-multi-tenant-sa-token ]](https://gitee.com/willf/springboot-multi-tenant-sa-token):轻量的多租户权限管理系统脚手架(SpringBoot,Sa-Token,mybatis-plus,Vue & Element)。
|
||||
|
||||
- [[ solon_angis_beetlsql ]](https://gitee.com/smartcity/solon_angis_beetlsql):并元国产开发平台 solon、sa-token、beetlsql、smart-http
|
||||
|
||||
- [[ zeta-kotlin ]](https://gitee.com/xia5800/zeta-kotlin):zeta-kotlin是使用kotlin语言基于spring boot、mybatis-plus、sa-token等框架开发的项目脚手架。
|
||||
|
||||
- [[ nebula-swagger-demo ]](https://gitee.com/flgitee/nebula-swagger-demo):springboot+nebula 集成knife4j案例
|
||||
|
||||
|
||||
### 微服务相关
|
||||
|
||||
@@ -69,8 +77,6 @@
|
||||
|
||||
- [[ falser-cloud ]](https://gitee.com/falser/falser-cloud): 基于 SpringCloud Alibaba + SpringCloud gateway + SpringBoot + Sa-Token + vue-admin-template + Nacos + Rabbit MQ + Redis 的一个后台管理系统,前后端分离,权限管理,菜单管理,数据字典,停车场系统管理等功能
|
||||
|
||||
- [[ Huanxing-mall ]](https://gitee.com/lijiaxing_boy/huanxing-mall):HuanXing 商城基于SpringCloud 2021 & Alibaba + Sa-token,前端基于 Vue3 +Element plus 的微服务商城
|
||||
|
||||
- [[ dcy-fast-cloud ]](https://gitee.com/dcy421/dcy-fast-cloud):一个基于 SpringCloudAlibaba + Sa-Token + dubbo2.7.8 + Seata + knife4j + Mybatis-Plus + MapStruct + 的后台管理系统,前端vue-element-admin,并且内置代码生成器+动态路由权限等功能
|
||||
|
||||
- [[ fhs-framework ]](https://gitee.com/fhs-opensource/fhs-framework):基于Springboot+Springcloud + Mybatis Plus + Sa-Token + Vue + ElementUI 的快速开发平台(低代码开发平台),本框架永远免费,永久全开源
|
||||
@@ -81,6 +87,30 @@
|
||||
|
||||
- [[ BudWk-V7 ]](https://gitee.com/budwk/budwk):基于 NutzBoot + Sa-Token + Dubbo + Nacos注册&配置中心 的微服务开发脚手架(同时提供单应用版本),带有配套后台管理前端模板及代码生成器
|
||||
|
||||
- [[ xr-satoken-cloud ]](https://gitee.com/fzhxfw/xr-satoken-cloud):一款基于SaToken轻量级Java权限认证框架构建的微服务后台开发脚手架,基于SpringCloud + SpringCloudAlibaba + Nacos + SaToken + Mybatis等技术搭建,内置RBAC权限管理,代码生成器,文件分片速传等,本项目完全开源免费,定期提交代码到dev开发分支,由个人开发者业余时间维护升级。
|
||||
|
||||
- [[ CloudEon ]](https://gitee.com/dromara/CloudEon):一款基于kubernetes的开源大数据平台,旨在为用户提供一种简单、高效、可扩展的大数据解决方案。
|
||||
|
||||
- [[ quick-boot ]](https://github.com/csx-bill/quick-boot):一款基于 Spring Cloud 2022 、Spring Boot 3、AMIS 和 APIJSON 的低代码系统。
|
||||
|
||||
|
||||
### 商城
|
||||
|
||||
- [[ litemall-plus ]](https://gitee.com/ysling-org/litemall-plus):微信小程序SaaS商城系统,可支持多小程序同时运行。
|
||||
|
||||
- [[ mall4j ]](https://gitee.com/gz-yami/mall4j):基于Spring Boot 3 JDK17的一个商城手脚架。
|
||||
|
||||
- [[ Huanxing-mall ]](https://gitee.com/lijiaxing_boy/huanxing-mall):HuanXing 商城基于SpringCloud 2021 & Alibaba + Sa-token,前端基于 Vue3 +Element plus 的微服务商城
|
||||
|
||||
|
||||
### 博客
|
||||
|
||||
- [[ jthink ]](https://gitee.com/wtsoftware/jthink): 一个基于 SpringBoot + Sa-Token + Thymeleaf 的博客系统
|
||||
|
||||
- [[ 拾壹博客 ]](https://gitee.com/quequnlong/shiyi-blog):一款vue+springboot前后端分离的博客系统,博客后台管理系统使用了vue+elmentui开发,后端使用Sa-Token进行权限管理,支持动态菜单权限,动态定时任务,文件支持本地和七牛云上传,使用ElasticSearch作为全文检索服务,支持QQ、微博、码云登录。
|
||||
|
||||
- [[ June 12 ]](https://gitee.com/hanshaung/ants):June 12 是一个纯开源免费的资讯/博客类网站,基于Spring Boot + Sa-Token + Vue开发。
|
||||
|
||||
|
||||
|
||||
### 插件
|
||||
@@ -93,17 +123,10 @@
|
||||
|
||||
### 其它
|
||||
|
||||
- [[ jthink ]](https://gitee.com/wtsoftware/jthink): 一个基于 SpringBoot + Sa-Token + Thymeleaf 的博客系统
|
||||
|
||||
- [[ Sa-Token-Study ]](https://gitee.com/click33/sa-token-study):以demo示例的方式讲解 Sa-Token 源码涉及到的技术点,连载中……
|
||||
- [[ Sa-Token-Study ]](https://gitee.com/sa-tokens/sa-token-study):以demo示例的方式讲解 Sa-Token 源码涉及到的技术点,连载中……
|
||||
|
||||
- [[ SpringMvc+Sa-Token ]](https://gitee.com/SRD_01/spring-mvc-sa-token): Jsp+SpringMVC+SSO+Sa-Token+Redis | Spring MVC 集成 SaToken Demo 项目
|
||||
|
||||
- [[ iot-kit ]](https://gitee.com/iotkit-open-source/iotkit-parent):一个轻量级低门槛的物联网平台,包含了多协议设备接入、规则引擎、第三方平台接入、智能家居小程序等模块的项目,基于SpringBoot架构并集成了Sa-Token的OAuth2认证。
|
||||
|
||||
- [[ 拾壹博客 ]](https://gitee.com/quequnlong/shiyi-blog):一款vue+springboot前后端分离的博客系统,博客后台管理系统使用了vue+elmentui开发,后端使用Sa-Token进行权限管理,支持动态菜单权限,动态定时任务,文件支持本地和七牛云上传,使用ElasticSearch作为全文检索服务,支持QQ、微博、码云登录。
|
||||
|
||||
- [[ cubic ]](https://gitee.com/dromara/cubic):一站式问题定位平台,实时线程栈监控、线程池监控、动态arthas命令集、依赖分析等等等,助你快速定位问题。
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -21,6 +21,30 @@ Sa-Token 采用 Apache-2.0 开源协议,**承诺框架本身与官网文档永
|
||||
|
||||
| 赞助人 | 赞助金额 | 留言 | 时间 |
|
||||
| :-------- | :-------- | :-------- | :-------- |
|
||||
| [时间很快](https://gitee.com/frsimple) | ¥ 220.0 | 感谢您的开源项目! | 2023-10-27 |
|
||||
| [立秋](https://gitee.com/code_wh) | ¥ 2.5 | 感谢您的开源项目! | 2023-10-27 |
|
||||
| [PotatoLoofah](https://gitee.com/PotatoLoofah) | ¥ 10.0 | 感谢您的开源项目! | 2023-10-27 |
|
||||
| [ly-chn](https://gitee.com/ly-chn) | ¥ 99.0 | 一定的资金支持有助于开源项目走的更加长远 | 2023-10-17 |
|
||||
| [yangs2w](https://gitee.com/yangs2w) | ¥ 10.0 | 感谢您的开源项目! | 2023-10-10 |
|
||||
| [lee](https://gitee.com/cngeeklee) | ¥ 10.0 | 真正的轻量级权限安全框架,希望继续更新 | 2023-10-06 |
|
||||
| [yang](https://gitee.com/hansdm) | ¥ 10.0 | 感谢您的开源项目! | 2023-09-27 |
|
||||
| [明道云](https://gitee.com/lunan-yn) | ¥ 200.0 | 明道云2023年伙伴大会,[报名链接](https://www.mingdao.com/event/mpc/2023) | 2023-09-25 |
|
||||
| [shenlicao](https://gitee.com/shenlicao) | ¥ 10.0 | 感谢您的开源项目! | 2023-09-15 |
|
||||
| [lostyue](https://gitee.com/lostyue) | ¥ 20.0 | 感谢您的开源项目! | 2023-09-14 |
|
||||
| [huni](https://gitee.com/simin_sizi) | ¥ 10.0 | 感谢您的开源项目! | 2023-09-11 |
|
||||
| [T_T](https://gitee.com/wm26hua) | ¥ 20.0 | 感谢您的开源项目! | 2023-09-07 |
|
||||
| [Meteor](https://gitee.com/meteoroc) | ¥ 2.5 | 感谢您的开源项目! | 2023-08-23 |
|
||||
| [刘斌](https://gitee.com/xuanfather) | ¥ 20.0 | 感谢您的开源项目! | 2023-08-17 |
|
||||
| [快快乐乐小码农](https://gitee.com/happy-little-farmer) | ¥ 1.0 | 感谢您的开源项目! | 2023-08-17 |
|
||||
| [失败女神](https://gitee.com/failedgoddess) | ¥ 50.0 | 感谢您的开源项目! | 2023-08-03 |
|
||||
| 结弦奏(微信打赏) | ¥ 50.0 | 感谢您的开源项目! | 2023-08-07 |
|
||||
| [好心肠的老哥](https://gitee.com/ntdm) | ¥ 10.0 | 非常好的开源项目,希望越来越好! | 2023-08-02 |
|
||||
| [XiaoYi](https://gitee.com/getianit) | ¥ 100.0 | [亚洲云深圳BGP云服务器](https://www.asiayun.com/cart?action=configureproduct&pid=300) | 2023-07-24 |
|
||||
| [张兆伟](https://gitee.com/zhang865700) | ¥ 50.0 | 感谢您的开源项目! | 2023-07-24 |
|
||||
| [mikeinshanghai](https://gitee.com/mikeinshanghai)| ¥ 50.0 | Sa-Token, MeterSphere共成长,共辉煌! | 2023-07-14 |
|
||||
| 吴其敏(微信打赏) | ¥ 200.0 | [CAT 是基于 Java 开发的实时应用监控平台,为美团点评提供了全面的实时监控告警服务。](https://github.com/dianping/cat) | 2023-07-11 |
|
||||
| [Dear胜哥](https://gitee.com/DearShengGe) | ¥ 10.0 | 有幸在摸鱼时间认真看完了全文档,感觉很是不错。开源不易,望作者继续扩展该框架功能! | 2023-06-30 |
|
||||
| [SP](https://gitee.com/LSP1999) | ¥ 10.0 | 就是需要这种简单上手的项目 | 2023-06-15 |
|
||||
| [javahuang](https://gitee.com/javahrp) | ¥ 200.0 | [SurveyKing:功能最强大的调查问卷系统和考试系统,开源](https://gitee.com/surveyking/surveyking) | 2023-06-08 |
|
||||
| [dyjgitdyjgit](https://gitee.com/qtinfogit) | ¥ 20.0 | 感谢您的开源项目! | 2023-05-22 |
|
||||
| 砰嚓嚓(QQ打赏) | ¥ 20.0 | 一点打赏不成敬意 | 2023-05-15 |
|
||||
@@ -142,9 +166,11 @@ Sa-Token 采用 Apache-2.0 开源协议,**承诺框架本身与官网文档永
|
||||
|
||||
### 商业赞助
|
||||
|
||||
一次性赞助 100 元或以上,可帮助您的产品在 Sa-Token 交流群艾特全体成员推广一次。
|
||||
一次性赞助 200 元或以上,可帮助您的产品在 Sa-Token 交流群艾特全体成员推广一次。
|
||||
|
||||
Sa-Token 目前总计10+微信交流群(每个群人数400以上,总人数5000+),4个QQ交流群(2000人群和1000人群,总计人数6000+),大部分为 java 开发工程师,可有效推广您的产品。
|
||||
并同时在赞助列表处高亮产品链接。
|
||||
|
||||
Sa-Token 目前总计14+微信交流群(每个群人数大约400以上,总计人数5000+),4个QQ交流群(2000人群和1000人群,总计人数6000+),大部分为 java 开发工程师,可有效推广您的产品。
|
||||
|
||||
- 优先推广和程序员相关的互联网产品,比如:低代码开发平台、网课、开发软件、云服务器、个人博客等等,实体产品如键盘、显示器、耳机等等,如果是和程序员无关的产品,可酌情考虑是否推广。
|
||||
- 拒绝接受违反法律法规、以及灰色相关的产品推广,为避免不必要的麻烦,目前也拒绝推广IP代理、上网工具等等。
|
||||
@@ -158,7 +184,7 @@ Sa-Token 目前总计10+微信交流群(每个群人数400以上,总人数50
|
||||
``` txt
|
||||
感谢 xx 老板对 Sa-Token 的商业赞助,以下是老板的产品,大家感兴趣的可以关注一下:
|
||||
xxx 商品名称
|
||||
链接:https://xxx.com/xxx
|
||||
链接:https://xxxxxn.com/xxx
|
||||
```
|
||||
|
||||
> 目前不接受 Sa-Token 官网文档插入广告推广,只接受一次性商业赞助推广。
|
||||
@@ -1,7 +1,34 @@
|
||||
# 更新日志
|
||||
|
||||
### v1.37.0 @2023-10-18
|
||||
- 修复:修复路由拦截鉴权可被绕过的问题。 **[漏洞修复]**
|
||||
- 重构:未登录时调用鉴权 API 抛出未登录异常而不再是无权限异常。
|
||||
- 优化:优化 SaTokenDao 组件更换时的逻辑。
|
||||
- 文档:提供 SpringBoot3.x 路由匹配出错的解决方案。
|
||||
|
||||
### 2023-6-23 @v1.35.0
|
||||
|
||||
### v1.36.0 @2023-9-22
|
||||
- sa-token-core:
|
||||
- 修复:API接口签名校验参数接口NPE问题,增加必须参数的非空校验处理。
|
||||
- 新增:加密工具类新增 sha384、sha512 实现。 感谢 `@若初995` 提交的pr。 **[重要]**
|
||||
- 修复:`SaFoxUtil.vagueMatch()` 正则匹配的一些问题。 **[漏洞修复]**
|
||||
- 修复:`SaRouter.match()` 路由匹配的一些问题。 **[漏洞修复]**
|
||||
- 其它:
|
||||
- 优化:`sa-token-alone-redis` 去掉不必要的配置项判断。
|
||||
- 新增:`sa-token-solon-plugin` 增加对 solon 网关的支持。
|
||||
- 新增:新增第三方插件专用仓库:`sa-token-three-plugin` 。
|
||||
- 升级:`sa-token-solon-plugin` 增加对 solon 网关的支持。
|
||||
- 文档:
|
||||
- 新增:新增开启全局懒加载时不能注入上下文处理器的处理方案 。
|
||||
- 新增:新增 RefreshToken 示例。 **[重要]**
|
||||
- 新增:文档新增 sa-token 小助手,可在线实时技术提问。 **[重要]**
|
||||
- 优化:其它一些优化。
|
||||
- 新增插件:
|
||||
- `sa-token-redisson-jackson2`:通用 redisson 集成方案 (spring, solon, jfinal 等都可用)
|
||||
|
||||
|
||||
|
||||
### v1.35.0 @2023-6-23
|
||||
- sa-token-core:
|
||||
- 优化:前端未提供 token 时,`getTokenSession()` 将抛出未登录异常,而不是返回 null。 **[不向下兼容]**
|
||||
- 新增:SaSession 新增字段:`type`、`loginType`、`loginId`、`token`。
|
||||
@@ -69,7 +96,7 @@
|
||||
- `sa-token-context-grpc` -> `sa-token-grpc`。
|
||||
|
||||
|
||||
### 2023-1-11 @v1.34.0
|
||||
### v1.34.0 @2023-1-11
|
||||
|
||||
新增插件:
|
||||
- 新增:新增 `SpringBoot3.x` 集成插件,感谢 `@jry` 提供的参考思路。 **[重要]**
|
||||
@@ -95,7 +122,7 @@ sa-token-sso 单点登录:
|
||||
|
||||
|
||||
|
||||
### 2022-11-16 @v1.33.0
|
||||
### v1.33.0 @2022-11-16
|
||||
- 重构:重构异常状态码机制。 **[重要]**
|
||||
- 重构:重构 sa-token-sso 模块异常码改为 300 开头,sa-token-jwt 异常码改为 302 开头。 **[不向下兼容]**
|
||||
- 新增:新增全局 Log 模块。 **[重要]**
|
||||
@@ -106,7 +133,7 @@ sa-token-sso 单点登录:
|
||||
|
||||
|
||||
|
||||
### 2022-10-28 @v1.32.0
|
||||
### v1.32.0 @2022-10-28
|
||||
- 修复:修复 sa-token-dao-redis-fastjson 插件多余序列化 `timeout` 字段的问题。
|
||||
- 修复:修复 sa-token-dao-redis-fastjson 插件 `session.getModel` 无法反序列化实体类的问题。
|
||||
- 修复:修复 `sa-token-quick-login` 插件指定拦截排除路由不生效的问题。
|
||||
@@ -146,7 +173,7 @@ sa-token-sso 单点登录:
|
||||
|
||||
|
||||
|
||||
### 2022-9-8 @v1.31.0
|
||||
### v1.31.0 @2022-9-8
|
||||
- 文档:新增优秀开源案例展示。
|
||||
- 文档:新增博客展示,欢迎大家投稿。
|
||||
- 新增:新增 `SaInterceptor` 综合拦截器。 **[重要]** **[不向下兼容]**
|
||||
@@ -185,7 +212,7 @@ sa-token-sso 单点登录:
|
||||
|
||||
|
||||
|
||||
### 2022-05-9 @v1.30.0
|
||||
### v1.30.0 @2022-05-9
|
||||
- 新增:新增集成 Web-Socket 鉴权示例。 **[重要]**
|
||||
- 新增:新增集成 Web-Socket(Spring封装版) 鉴权示例。
|
||||
- 新增:新增 jfinal 集成包 `sa-token-jfinal-plugin` **[重要]**
|
||||
@@ -230,7 +257,7 @@ sa-token-sso 单点登录:
|
||||
- 修复:修复 `StpLogicJwtForSimple` 模式下 Extra 数据可能受到旧 token 影响的bug
|
||||
|
||||
|
||||
### 2022-02-10 @v1.29.0
|
||||
### v1.29.0 @2022-02-10
|
||||
- 升级:sa-token-jwt插件可在登录时添加额外数据。
|
||||
- 重构:优化Dubbo调用时向下传递Token的规则,可避免在项目启动时由于Context无效引发的bug。
|
||||
- 重构:OAuth2 授权模式开放由全局配置和Client单独配置共同设定。
|
||||
@@ -252,7 +279,7 @@ sa-token-sso 单点登录:
|
||||
- 完善:完善单元测试。
|
||||
|
||||
|
||||
### 2021-11-5 @v1.28.0
|
||||
### v1.28.0 @2021-11-5
|
||||
- 新增:新增 `sa-token-jwt` 插件,用于与jwt的整合 **[重要]**
|
||||
- 新增:新增 `sa-token-context-dubbo` 插件,用于与 Dubbo 的整合 **[重要]**
|
||||
- 文档:文档新增章节:Sa-Token 插件开发指南 **[重要]**
|
||||
@@ -266,7 +293,7 @@ sa-token-sso 单点登录:
|
||||
- 文档:新增常见问题总结
|
||||
|
||||
|
||||
### 2021-10-11 @v1.27.0
|
||||
### v1.27.0 @2021-10-11
|
||||
- 升级:增强 SaRouter 链式匹配能力 **[重要]**
|
||||
- 新增:新增插件 Thymeleaf 标签方言 **[重要]**
|
||||
- 新增:@SaCheckPermission 增加 orRole 字段,用于权限角色“双重or”匹配 **[重要]**
|
||||
@@ -291,7 +318,7 @@ sa-token-sso 单点登录:
|
||||
- [不向下兼容] 侦听器 doLogoutByLoginId 方法重命名为 doKickout
|
||||
|
||||
|
||||
### 2021-9-2 @v1.26.0
|
||||
### v1.26.0 @2021-9-2
|
||||
- 优化:优化单点登录文档
|
||||
- 新增:新增 `Http Basic` 认证 **[重要]**
|
||||
- 新增:文档新增跨域解决方案
|
||||
@@ -300,7 +327,7 @@ sa-token-sso 单点登录:
|
||||
- 示例:新增 `SSO-Server` 端前后端分离示例 **[重要]**
|
||||
|
||||
|
||||
### 2021-8-16 @v1.25.0
|
||||
### v1.25.0 @2021-8-16
|
||||
- 新增:`SaRequest`新增`getHeader(name, defaultValue)`方法,用于获取header默认值
|
||||
- 新增:`SaRequest` 添加 `forward` 转发方法
|
||||
- 新增:Readme新增源码模块介绍、友情链接、正在使用Sa-Token的项目
|
||||
@@ -320,7 +347,7 @@ sa-token-sso 单点登录:
|
||||
- 重构:修复 `SaReactorHolder.getContent()` 拼写错误:`content` -> `context`
|
||||
|
||||
|
||||
### 2021-7-24 @v1.24.0
|
||||
### v1.24.0 @2021-7-24
|
||||
- 修复:修复部分场景下Alone-Redis插件导致项目无法启动的问题
|
||||
- 优化:增加对SpringBoot1.x版本的兼容性
|
||||
- 新增:SaOAuth2Util新增checkScope函数,用于校验令牌是否具备指定权限
|
||||
@@ -330,14 +357,14 @@ sa-token-sso 单点登录:
|
||||
- 优化:大幅度优化文档示例
|
||||
|
||||
|
||||
### 2021-7-19 @v1.23.0
|
||||
### v1.23.0 @2021-7-19
|
||||
- 新增:Sa-Token-OAuth2 模块正式发布 **[重要]**
|
||||
- 修复:修复jwt集成demo无法正确注册StpLogic的bug
|
||||
- 修复:修复登录时某些场景下Session续期可能不正常的bug
|
||||
- 优化:代码注释优化,文档优化
|
||||
|
||||
|
||||
### 2021-7-10 @v1.22.0
|
||||
### v1.22.0 @2021-7-10
|
||||
- 新增:SaSsoConfig 部分属性增加set连缀风格
|
||||
- 优化:SaSsoUtil 可定制化底层的 `StpLogic`
|
||||
- 新增:新增 `SaSsoHandle` 大幅度简化单点登录整合步骤 **[重要]**
|
||||
@@ -346,7 +373,7 @@ sa-token-sso 单点登录:
|
||||
- 优化:大幅度优化文档示例
|
||||
|
||||
|
||||
### 2021-7-2 @v1.21.0
|
||||
### v1.21.0 @2021-7-2
|
||||
- 新增:新增Token二级认证 **[重要]**
|
||||
- 新增:新增`Sa-Token-Alone-Redis`独立Redis插件 **[重要]**
|
||||
- 新增:新增SSO三种模式,彻底解决所有场景下的单点登录问题 **[重要]**
|
||||
@@ -356,7 +383,7 @@ sa-token-sso 单点登录:
|
||||
- 更改yml配置前缀:原`[spring.sa-token.]` 改为 `[sa-token.]`,目前版本暂时向下兼容,请尽快更新
|
||||
|
||||
|
||||
### 2021-6-17 @v1.20.0
|
||||
### v1.20.0 @2021-6-17
|
||||
- 新增:新增Solon适配插件,感谢大佬 `@刘西东` 提供的pr **[重要]**
|
||||
- 新增:新增`SaRouter.stop()`函数,用于一次性跳出匹配链功能 **[重要]**
|
||||
- 新增:新增单元测试 **[重要]**
|
||||
@@ -377,7 +404,7 @@ sa-token-sso 单点登录:
|
||||
- 为保证平滑更新,旧API仍旧保留,但已增加`@Deprecated`注解,请尽快更新至新API
|
||||
|
||||
|
||||
### 2021-5-10 @v1.19.0
|
||||
### v1.19.0 @2021-5-10
|
||||
- 新增:注解鉴权新增定制loginType功能 **[重要]**
|
||||
- 重构:重构目录结构,抽离`plugin`模块 **[重要]**
|
||||
- 新增:新增 `sa-token-quick-login` 插件,零代码集成登录功能 **[重要]**
|
||||
@@ -385,7 +412,7 @@ sa-token-sso 单点登录:
|
||||
- 优化:文档优化...
|
||||
|
||||
|
||||
### 2021-4-24 @v1.18.0
|
||||
### v1.18.0 @2021-4-24
|
||||
- 新增:新增权限通配符功能,灵活设置权限 **[重要]**
|
||||
- 修复:修复自动续签处的逻辑错误
|
||||
- 新增:新增Web开发常见漏洞防护建议
|
||||
@@ -398,7 +425,7 @@ sa-token-sso 单点登录:
|
||||
- 重构:`SaTokenInsideUtil` -> `SaFoxUtil`
|
||||
|
||||
|
||||
### 2021-4-17 @v1.17.0
|
||||
### v1.17.0 @2021-4-17
|
||||
- 修复:在WebFlux环境中引入Redis集成包无法启动的问题
|
||||
- 修复:修复JWT集成示例中版本升级API的变更
|
||||
- 优化:优化启动时字符画打印
|
||||
@@ -409,7 +436,7 @@ sa-token-sso 单点登录:
|
||||
- 新增:新增全局侦听器,可在用户登陆、注销、被踢下线等关键性操作时进行一些AOP操作 **[重要]**
|
||||
|
||||
|
||||
### 2021-4-12 @v1.16.0
|
||||
### v1.16.0 @2021-4-12
|
||||
- 新增:新增账号封禁功能,指定时间内账号无法登陆 **[重要]**
|
||||
- 新增:核心包脱离`ServletAPI`,彻底零依赖! **[重要]**
|
||||
- 新增:新增基于`ThreadLocal`的上下文容器 **[重要]**
|
||||
@@ -420,7 +447,7 @@ sa-token-sso 单点登录:
|
||||
- 文档:新增推荐公众号列表
|
||||
|
||||
|
||||
### 2021-3-23 @v1.15.0
|
||||
### v1.15.0 @2021-3-23
|
||||
- 新增:文档添加源码涉及技术栈说明
|
||||
- 优化:优化路由拦截器模块文档,更简洁的示例
|
||||
- 修复:修复非web环境下的错误提示,Request->Response
|
||||
@@ -440,7 +467,7 @@ sa-token-sso 单点登录:
|
||||
- `SaRouteInterceptor`去出冗余API,详情参考路由鉴权部分
|
||||
|
||||
|
||||
### 2021-3-12 @v1.14.0
|
||||
### v1.14.0 @2021-3-12
|
||||
- 新增:新增`SaLoginModel`登录参数Model,适配 [记住我] 模式 **[重要]**
|
||||
- 新增:新增 `StpUtil.login()` 时指定token有效期,可灵活控制用户的一次登录免验证时长
|
||||
- 新增:新增Cookie时间判断,在`timeout`设置为-1时,`Cookie`有效期将为`Integer.MAX_VALUE` **[重要]**
|
||||
@@ -458,7 +485,7 @@ sa-token-sso 单点登录:
|
||||
- 文档:优化文档,部分模块添加图片说明
|
||||
|
||||
|
||||
### 2021-2-9 @v1.13.0
|
||||
### v1.13.0 @2021-2-9
|
||||
- 优化:优化源码注释与文档
|
||||
- 新增:文档集成Gitalk评论系统
|
||||
- 优化:源码包`Maven`版本号更改为变量形式
|
||||
@@ -473,7 +500,7 @@ sa-token-sso 单点登录:
|
||||
- 新增:完善分布式会话的文档说明
|
||||
|
||||
|
||||
### 2021-1-12 @v1.12.0
|
||||
### v1.12.0 @2021-1-12
|
||||
- 新增:提供JWT集成示例 **[重要]**
|
||||
- 新增:新增路由式鉴权,可方便的根据路由匹配鉴权 **[重要]**
|
||||
- 新增:新增身份临时切换功能,可在一个代码段内将会话临时切换为其它账号 **[重要]**
|
||||
@@ -482,23 +509,23 @@ sa-token-sso 单点登录:
|
||||
- 升级:v1.12.1,新增`SaRouterUtil`工具类,更方便的路由鉴权 **[重要]**
|
||||
|
||||
|
||||
### 2021-1-10 @v1.11.0
|
||||
### v1.11.0 @2021-1-10
|
||||
- 新增:提供AOP注解鉴权方案 **[重要]**
|
||||
- 优化自动生成token的算法
|
||||
|
||||
|
||||
### 2021-1-9 @v1.10.0
|
||||
### v1.10.0 @2021-1-9
|
||||
- 新增:提供查询所有会话方案 **[重要]**
|
||||
- 修复:修复token设置为永不过期时无法正常被顶下线的bug,感谢github用户 @zjh599245299 提出的bug
|
||||
|
||||
|
||||
### 2021-1-6 @v1.9.0
|
||||
### v1.9.0 @2021-1-6
|
||||
- 优化:`spring-boot-starter-data-redis` 由 `2.3.7.RELEASE` 改为 `2.3.3.RELEASE`
|
||||
- 修复:补上注解拦截器里漏掉验证`@SaCheckRole`的bug
|
||||
- 新增:新增同端互斥登录,像QQ一样手机电脑同时在线,但是两个手机上互斥登录 **[重要]**
|
||||
|
||||
|
||||
### 2021-1-2 @v1.8.0
|
||||
### v1.8.0 @2021-1-2
|
||||
- 优化:优化源码注释
|
||||
- 修复:修复部分文档错别字
|
||||
- 修复:修复项目文件夹名称错误
|
||||
@@ -517,7 +544,7 @@ sa-token-sso 单点登录:
|
||||
- 升级:开源协议修改为`Apache-2.0`
|
||||
|
||||
|
||||
### 2020-12-24 @v1.7.0
|
||||
### v1.7.0 @2020-12-24
|
||||
- 优化:项目架构改为maven多模块形式,方便增加新模块 **[重要]**
|
||||
- 优化:与`springboot`的集成改为`springboot-starter`模式,无需`@SaTokenSetup`注解即可完成自动装配 **[重要]**
|
||||
- 新增:新增`activity-timeout`配置,可控制token临时过期与续签功能 **[重要]**
|
||||
@@ -527,13 +554,13 @@ sa-token-sso 单点登录:
|
||||
- 修复:修复文档首页样式问题
|
||||
|
||||
|
||||
### 2020-12-17 @v1.6.0
|
||||
### v1.6.0 @2020-12-17
|
||||
- 新增:花式token生成方案 **[重要]**
|
||||
- 优化:优化`readme.md`
|
||||
- 修复:修复`SaCookieOper`与`SaTokenAction`无法自动注入的问题
|
||||
|
||||
|
||||
### 2020-12-16 @v1.5.1
|
||||
### v1.5.1 @2020-12-16
|
||||
- 新增:细化未登录异常类型,提供五种场景值:未提供token、token无效、token已过期 、token已被顶下线、token已被踢下线 **[重要]**
|
||||
- 修复:修复`StpUtil.getSessionByLoginId(String loginId)`方法转换key出错的bug,感谢群友 @(#°Д°)、@一米阳光 发现的bug
|
||||
- 优化:修改方法`StpUtil.getSessionByLoginId(Object loginId)`的isCreate值默认为true
|
||||
@@ -547,7 +574,7 @@ sa-token-sso 单点登录:
|
||||
- 升级:开源协议修改为`MIT`
|
||||
|
||||
|
||||
### 2020-9-7 @v1.4.0
|
||||
### v1.4.0 @2020-9-7
|
||||
- 优化:修改一些函数、变量名称,使其更符合阿里java代码规范
|
||||
- 优化:`tokenValue`的读取优先级改为:`request` > `body` > `header` > `cookie` **[重要]**
|
||||
- 新增:新增`isReadCookie`配置,决定是否从`cookie`里读取`token`信息
|
||||
@@ -556,7 +583,7 @@ sa-token-sso 单点登录:
|
||||
- 修复:修复文档部分错误,修正群号码
|
||||
|
||||
|
||||
### 2020-5-2 @v1.3.0
|
||||
### v1.3.0 @2020-5-2
|
||||
- 新增:新增 `StpUtil.checkLogin()` 方法,更符合语义化的鉴权方法
|
||||
- 新增:注册拦截器时可设置 `StpLogic` ,方便不同模块不同鉴权方式
|
||||
- 新增:抛出异常时增加 `loginType` 区分,方便多账号体系鉴权处理
|
||||
@@ -565,14 +592,14 @@ sa-token-sso 单点登录:
|
||||
- 新增:新增文档的友情链接
|
||||
|
||||
|
||||
### 2020-3-7 @v1.2.0
|
||||
### v1.2.0 @2020-3-7
|
||||
- 新增:新增注解式验证,可在路由方法中使用注解进行权限验证 **[重要]**
|
||||
- 参考:[注解式验证](use/at-check)
|
||||
|
||||
|
||||
### 2020-2-12 @v1.1.0
|
||||
### v1.1.0 @2020-2-12
|
||||
- 修复:修复`StpUtil.getLoginId(T defaultValue)`取值转换错误的bug
|
||||
|
||||
|
||||
### 2020-2-4 @v1.0.0
|
||||
### v1.0.0 @2020-2-4
|
||||
- 第一个版本出炉
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
- sa-token-redis-fastjson:Redis集成包,使用 fastjson 序列化方式。
|
||||
- sa-token-redis-fastjson2:Redis集成包,使用 fastjson2 序列化方式。
|
||||
- sa-token-redisson-jackson:Redis集成包,Redisson客户端使用,jackson 序列化方式。
|
||||
- sa-token-redisson-jackson2:通用 redisson 集成方案 (spring, solon, jfinal 等都可用)。
|
||||
|
||||
有关 Redis 集成,详细参考:[集成Redis](/up/integ-redis),更多存储方式欢迎提交PR
|
||||
|
||||
|
||||
@@ -103,7 +103,10 @@ public class SaTokenConfigure {
|
||||
|
||||
首先在 SaTokenConfigure 配置类中为 Thymeleaf 配置全局对象:
|
||||
|
||||
(注意: 如果`SaTokenConfigure`继承了`WebMvcConfigurer`等类, 可能会造成循环依赖, 如果遇到, 请新建一个其他配置类完成此项配置)
|
||||
|
||||
``` java
|
||||
@Configuration
|
||||
public class SaTokenConfigure{
|
||||
// ... 其它代码
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
比如:用户账号增删改查维护、登录日志统计、新增用户数据报表、新增 Client 应用接入域名配置……等等,
|
||||
仍需要大量的开发时间。
|
||||
|
||||
为此,我们特意准备了项目:[[ Sa-Sso-Pro 单点登录商业版 ]](http://sa-pro.dev33.cn/index.html?hmsr=sa-token),
|
||||
为此,我们特意准备了项目:[[ Sa-Sso-Pro 单点登录商业版 ]](http://sa-pro.dev33.cn?hmsr=sa-token),
|
||||
项目集成了单点登录常见技术点, 绝大多数功能无需二次开发,直接可用,<b style="color: #FF5722;">可大大缩短您的项目接入单点登录的开发周期</b>。
|
||||
|
||||
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
---
|
||||
|
||||
### 正式版本
|
||||
v1.34.0 正式版,可上生产:
|
||||
v1.37.0 正式版,可上生产:
|
||||
|
||||
``` xml
|
||||
<!-- Sa-Token 权限认证 -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot-starter</artifactId>
|
||||
<version>1.34.0</version>
|
||||
<version>1.37.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
||||
@@ -329,3 +329,27 @@ body {
|
||||
}
|
||||
.main-box details p{padding: 0 14px;}
|
||||
|
||||
/* 顶部广告 */
|
||||
#main .top-ad-box{padding: 0.5em 1em; font-size: 12px; margin-bottom: 30px; background-color: rgba(0, 0, 0, 0.04);}
|
||||
#main .top-ad-box a{border-bottom: 0px;}
|
||||
#main .top-ad-box a:hover{border-bottom: 0px;}
|
||||
#main .top-ad-box a img{border: 0px #ddd solid; width: 100%; /* max-height: 80px; */
|
||||
border-radius: 2px; transition: all 0.2s;}
|
||||
#main .top-ad-box a img:hover{box-shadow: 0 0 20px #ddd;}
|
||||
.ad-tips{color: #aaa;}
|
||||
.ad-close{float: right;}
|
||||
.ad-close:hover{cursor: pointer; text-decoration: underline; color: red;}
|
||||
|
||||
|
||||
/* 帮助按钮 */
|
||||
.help-btn{transition: all 0.2s;}
|
||||
.help-btn:hover{box-shadow: 0 0 30px #aaa !important;}
|
||||
.xiaozhushou-intro p{line-height: 16px;}
|
||||
|
||||
/* 按钮发光动画 */
|
||||
.help-btn{animation: helpbtnanimation 3s infinite;}
|
||||
@keyframes helpbtnanimation{
|
||||
0%{box-shadow: 0 0 1px #42B983;}
|
||||
50%{box-shadow: 0 0 20px #42B983;}
|
||||
100%{box-shadow: 0 0 20px #FFF;}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ var myDocsifyPlugin = function(hook, vm) {
|
||||
return html + footer;
|
||||
});
|
||||
|
||||
// 每钩子函数:次路由切换时数据全部加载完成后调用,没有参数。
|
||||
// 钩子函数:每次路由切换时数据全部加载完成后调用,没有参数。
|
||||
hook.doneEach(function() {
|
||||
|
||||
// 功能3,给代码盒子,添加行数样式
|
||||
@@ -59,6 +59,54 @@ var myDocsifyPlugin = function(hook, vm) {
|
||||
if($('.zanzhu-count').length && $('.zanzhu-box table').length) {
|
||||
$('.zanzhu-count').html($('.zanzhu-box table tr').length);
|
||||
}
|
||||
|
||||
// 功能6:标题下面的广告
|
||||
if(vm.route.path !== '/' && $(window).width() >= 800) {
|
||||
var ad = `<p class="top-ad-box">
|
||||
<span class="ad-tips">推广信息:</span>
|
||||
<span class="ad-tips ad-close">关闭</span>
|
||||
<a href="http://sa-pro.dev33.cn?from=satop" target="_blank">
|
||||
<img src="https://oss.dev33.cn/sa-token/ad/sa-sso-pro-x.png" />
|
||||
</a>
|
||||
</p>`;
|
||||
|
||||
// 没有下划线就先补个下划线
|
||||
// if($('#main h1').next().prop('tagName') !== 'HR') {
|
||||
// $('#main h1').after('<hr/>');
|
||||
// }
|
||||
|
||||
// 如果一周内用户点击过关闭广告,则不再展现
|
||||
let allowJg = 1000 * 60 * 60 * 24 * 7;
|
||||
// allowJg = 1000 * 10;
|
||||
try{
|
||||
const closeAdTime = localStorage.closeAdTime;
|
||||
if(closeAdTime) {
|
||||
// 点击广告关闭的时间,和当前时间的差距
|
||||
const closeAdJg = new Date().getTime() - parseInt(closeAdTime);
|
||||
|
||||
// 差距小于七天,不再展示
|
||||
if(closeAdJg < allowJg) {
|
||||
console.log('not show ad ...');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}catch(e){
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
|
||||
// 添加广告
|
||||
$('#main h1').after(ad);
|
||||
// 添加关闭事件
|
||||
$('.top-ad-box .ad-close').click(function(){
|
||||
console.log('关闭广告');
|
||||
// $('.top-ad-box').slideUp(); // 折叠收起
|
||||
$(".top-ad-box").fadeOut(1000); // 淡出效果
|
||||
layer.msg('一周内不再展现此信息')
|
||||
localStorage.closeAdTime = new Date().getTime();
|
||||
})
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// 钩子函数:初始化并第一次加载完成数据后调用,没有参数。
|
||||
|
||||
@@ -0,0 +1,259 @@
|
||||
//
|
||||
|
||||
// 声明 docsify 插件
|
||||
var isStarPlugin = function(hook, vm) {
|
||||
|
||||
// 钩子函数:解析之前执行
|
||||
hook.beforeEach(function(content) {
|
||||
return content;
|
||||
});
|
||||
|
||||
// 钩子函数:每次路由切换时,解析内容之后执行
|
||||
hook.afterEach(function(html) {
|
||||
return html;
|
||||
});
|
||||
|
||||
// 钩子函数:每次路由切换时数据全部加载完成后调用,没有参数。
|
||||
hook.doneEach(function() {
|
||||
isStarRepo(vm);
|
||||
});
|
||||
|
||||
// 钩子函数:初始化并第一次加载完成数据后调用,没有参数。
|
||||
hook.ready(function() {
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// 应用参数
|
||||
const client_id = '0cc618beb08db99bff50e500e38c2144d95ada9abb51c00c44592726ecd583f4';
|
||||
const client_secret = 'xxx';
|
||||
const redirect_uri = 'https://sa-token.cc/doc.html';
|
||||
const docDomain = 'sa-token.cc';
|
||||
// const redirect_uri = 'http://127.0.0.1:8848/sa-token-doc/doc.html';
|
||||
// const docDomain = '127.0.0.1:8848';
|
||||
|
||||
// 检查成功后,多少天不再检查
|
||||
const allowDisparity = 1000 * 60 * 60 * 24 * 30 * 3;
|
||||
// const allowDisparity = 1000 * 10;
|
||||
|
||||
|
||||
// 判断当前是否已 star
|
||||
function isStarRepo(vm) {
|
||||
// 非PC端不检查
|
||||
if(document.body.offsetWidth < 800) {
|
||||
console.log('small screen ...');
|
||||
return;
|
||||
}
|
||||
|
||||
// 判断是否在主域名下
|
||||
if(location.host !== docDomain) {
|
||||
console.log('not domain, no check...');
|
||||
return;
|
||||
}
|
||||
|
||||
// 判断是否近期已经判断过了
|
||||
try{
|
||||
const isStarRepo = localStorage.isStarRepo;
|
||||
if(isStarRepo) {
|
||||
// 记录 star 的时间,和当前时间的差距
|
||||
const disparity = new Date().getTime() - parseInt(isStarRepo);
|
||||
|
||||
// 差距小于一月,不再检测,大于一月,再检测一下
|
||||
if(disparity < allowDisparity) {
|
||||
console.log('checked ...');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}catch(e){
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
// 白名单路由不判断
|
||||
const whiteList = ['/a', '/more/link', '/more/demand-commit', '/more/join-group', '/more/sa-token-donate',
|
||||
'/sso/sso-pro', '/more/update-log', '/more/common-questions', '/fun/sa-token-test', '/fun/issue-template'];
|
||||
if(whiteList.indexOf(vm.route.path) >= 0 && getParam('code') === null) {
|
||||
console.log('white route ...');
|
||||
return;
|
||||
}
|
||||
|
||||
// 开始获取 code
|
||||
$('body').css({'overflow': 'hidden'});
|
||||
getCode();
|
||||
}
|
||||
|
||||
// 去请求授权
|
||||
function getCode() {
|
||||
|
||||
// 检查url中是否有code
|
||||
const code = getParam('code');
|
||||
if(code) {
|
||||
// 有 code,进一步去请求 access_token
|
||||
getAccessToken(code);
|
||||
} else {
|
||||
// 不存在code,弹窗提示询问
|
||||
confirmStar();
|
||||
}
|
||||
}
|
||||
|
||||
// 弹窗提示点 star
|
||||
function confirmStar() {
|
||||
|
||||
// 弹窗提示文字
|
||||
const tipStr = `
|
||||
<div>
|
||||
<p><b>嗨,同学,来支持一下 Sa-Token 吧,为项目点个 star !</b></p>
|
||||
<div>仅需两步即可完成:<br>
|
||||
<div>1、打开 Sa-Token <a href="https://gitee.com/dromara/sa-token" target="_blank">开源仓库主页</a>,在右上角点个 star 。</div>
|
||||
<div>2、点击下方 [ 同意授权检测 ] 按钮,同意 Sa-Token 获取 API 权限进行检测。<a href="javascript:authDetails();" style="text-decoration: none;">?</a></div>
|
||||
</div>
|
||||
<p><b>本章节文档将在 star 后正常开放展示。</b></p>
|
||||
<p style="color: green;">开源不易,希望您不吝支持,激励开源项目走的更加长远 😇😇😇</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const index = layer.confirm(tipStr, {
|
||||
title: '提示',
|
||||
btn: ['同意授权检测'],
|
||||
// btn: ['同意授权检测', '暂时不要,我先看看文档'],
|
||||
area: '460px',
|
||||
offset: '25%',
|
||||
closeBtn: false
|
||||
},
|
||||
function(index) {
|
||||
//
|
||||
layer.close(index);
|
||||
// 用户点了确认,去 gitee 官方请求授权获取
|
||||
goAuth();
|
||||
}
|
||||
);
|
||||
|
||||
// 源码注释提示
|
||||
const closeLayer =
|
||||
`
|
||||
<!--
|
||||
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
|
||||
在 f12 控制台 执行一下:
|
||||
localStorage.isStarRepo = new Date().getTime()
|
||||
即可取消弹窗 ,执行完刷新一下页面
|
||||
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
|
||||
-->
|
||||
`;
|
||||
$('#layui-layer' + index).prepend(closeLayer)
|
||||
}
|
||||
|
||||
|
||||
// 跳转到 gitee 授权界面
|
||||
function goAuth() {
|
||||
const authUrl = "https://gitee.com/oauth/authorize" +
|
||||
"?client_id=" + client_id +
|
||||
"&redirect_uri=" + redirect_uri +
|
||||
"&response_type=code";
|
||||
location.href = authUrl;
|
||||
}
|
||||
|
||||
|
||||
// 获取 access_token
|
||||
function getAccessToken(code) {
|
||||
// 根据 code 获取 access_token
|
||||
$.ajax({
|
||||
url: 'https://sa-token.cc/server/oauth/token',
|
||||
method: 'post',
|
||||
data: {
|
||||
grant_type: 'authorization_code',
|
||||
code: code,
|
||||
client_id: client_id,
|
||||
redirect_uri: redirect_uri,
|
||||
client_secret: client_secret,
|
||||
},
|
||||
success: function(res) {
|
||||
// 如果返回的不是 200
|
||||
if(res.code !== 200) {
|
||||
return layer.alert(res.msg, {closeBtn: false}, function(){
|
||||
// 刷新url,去掉 code 参数
|
||||
location.href = 'doc.html';
|
||||
});
|
||||
}
|
||||
|
||||
// 拿到 access_token
|
||||
const access_token = res.access_token;
|
||||
|
||||
// 根据 access_token 判断是否 star 了仓库
|
||||
$.ajax({
|
||||
url: 'https://gitee.com/api/v5/user/starred/dromara/sa-token',
|
||||
method: 'get',
|
||||
data: {
|
||||
access_token: access_token
|
||||
},
|
||||
success: function(res) {
|
||||
// success 回调即代表已经 star,gitee API 请求体不返回任何数据
|
||||
console.log('-> stared ...');
|
||||
// 记录本次检查时间
|
||||
localStorage.isStarRepo = new Date().getTime();
|
||||
//
|
||||
layer.alert('感谢你的支持 ❤️ ❤️ ❤️ ,Sa-Token 将努力变得更加完善!', function(index) {
|
||||
layer.close(index);
|
||||
// 刷新url,去掉 code 参数
|
||||
location.href = location.href.replace("?code=" + code, '');
|
||||
})
|
||||
},
|
||||
error: function(e) {
|
||||
// console.log('ff请求错误 ', e);
|
||||
// 如下返回,代表没有 star
|
||||
if(e.statusText = 'Not Found'){
|
||||
console.log('not star ...');
|
||||
layer.alert('未检测到 star 数据...', {closeBtn: false}, function() {
|
||||
// 刷新url,去掉 code 参数
|
||||
location.href = location.href.replace("?code=" + code, '');
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
error: function(e) {
|
||||
console.log('请求错误 ', e);
|
||||
// 如果请求地址有错,可能是服务器宕机了,暂停一天检测
|
||||
if(e.status === 0 || e.status === 502) {
|
||||
return layer.alert(JSON.stringify(e), {closeBtn: false}, function(){
|
||||
// 一天内不再检查
|
||||
const ygTime = allowDisparity - (1000 * 60 * 60 * 24);
|
||||
localStorage.isStarRepo = new Date().getTime() - ygTime;
|
||||
// 刷新 url,去掉 code 参数
|
||||
location.href = location.href.replace("?code=" + code, '');
|
||||
});
|
||||
}
|
||||
|
||||
// 无效授权,可能是 code 无效
|
||||
const errorMsg = (e.responseJSON && e.responseJSON.error) || JSON.stringify(e);
|
||||
if(errorMsg == 'invalid_grant') {
|
||||
console.log('无效code', code);
|
||||
}
|
||||
layer.alert('check error... ' + errorMsg, function(index) {
|
||||
layer.close(index);
|
||||
// 刷新url,去掉 code 参数
|
||||
let url = location.href.replace("?code=" + code, '');
|
||||
url = url.replace("&code=" + code, '');
|
||||
location.href = url;
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 疑问
|
||||
function authDetails() {
|
||||
const str = "用于检测的凭证信息将仅保存你的浏览器本地,Sa-Token 文档已完整开源,源码可查";
|
||||
alert(str);
|
||||
}
|
||||
|
||||
// 获取 url 携带的参数
|
||||
function getParam(name, defaultValue){
|
||||
var query = window.location.search.substring(1);
|
||||
var vars = query.split("&");
|
||||
for (var i=0;i<vars.length;i++) {
|
||||
var pair = vars[i].split("=");
|
||||
if(pair[0] == name){return pair[1];}
|
||||
}
|
||||
return(defaultValue == undefined ? null : defaultValue);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
@charset "utf-8";
|
||||
/* CSS Document */
|
||||
|
||||
/* ry盒子 总区域 */
|
||||
.ry-kuai{
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
/* ry盒子 灰色区域 */
|
||||
.ry-box{
|
||||
padding-top: 70px;
|
||||
padding-bottom: 170px;
|
||||
background-color: #eee;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 轮播图容器 */
|
||||
.ry-box .swiper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.ry-box .swiper-slide {
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
width: 750px;
|
||||
height: 500px;
|
||||
/* cursor: pointer; */
|
||||
}
|
||||
.ry-box .swiper-slide-tx1{
|
||||
width: 450px;
|
||||
}
|
||||
|
||||
.ry-box .swiper-slide img {
|
||||
height: 100%;
|
||||
box-shadow: 0 0 20px #ccc;
|
||||
transition: box-shadow 0.2s;
|
||||
}
|
||||
.ry-box .swiper-slide img:hover{
|
||||
box-shadow: 0 0 40px #999;
|
||||
}
|
||||
.ry-box .swiper-slide p{
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
margin-top: 30px;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
|
||||
/* 分页器样式 */
|
||||
.ry-box .swiper-pagination{bottom: -140px;}
|
||||
.ry-box .swiper-pagination .swiper-pagination-bullet{width: 18px; height: 18px; line-height: 18px; color: #FFF; font-size: 12px;}
|
||||
|
||||
/* 图片放大动画 */
|
||||
.ry-box .swiper-slide img{
|
||||
transition: 300ms;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
.ry-box .swiper-slide-active img,
|
||||
.ry-box .swiper-slide-duplicate-active img{
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
/* 阴影 */
|
||||
/* .ry-img-yinying{
|
||||
width: 50%; height: 10px; border-radius: 50%;
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
box-shadow: 0 0 50px #333;
|
||||
margin: auto;
|
||||
} */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user