将整合redis的demo独立出来

This commit is contained in:
click33 2022-05-06 10:32:55 +08:00
parent 7e399fb63a
commit af2d851ddb
19 changed files with 2103 additions and 0 deletions

View File

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

View File

@ -0,0 +1,72 @@
<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-springboot-redis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- SpringBoot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.12</version>
<!-- <version>1.5.9.RELEASE</version> -->
<relativePath/>
</parent>
<!-- 定义sa-token版本号 -->
<properties>
<sa-token-version>1.30.0.RC</sa-token-version>
</properties>
<dependencies>
<!-- SpringBoot依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- Sa-Token 权限认证, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>${sa-token-version}</version>
</dependency>
<!-- Sa-Token 整合 Redis (使用jdk默认序列化方式) -->
<!-- <dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis</artifactId>
<version>${sa-token-version}</version>
</dependency> -->
<!-- Sa-Token整合 Redis (使用jackson序列化方式) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis-jackson</artifactId>
<version>${sa-token-version}</version>
</dependency>
<!-- 提供Redis连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- @ConfigurationProperties -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,62 @@
package com.pj;
import org.springframework.stereotype.Component;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.stp.SaLoginModel;
/**
* 自定义侦听器的实现
*/
@Component
public class MySaTokenListener implements SaTokenListener {
/** 每次登录时触发 */
@Override
public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {
// ...
}
/** 每次注销时触发 */
@Override
public void doLogout(String loginType, Object loginId, String tokenValue) {
// ...
}
/** 每次被踢下线时触发 */
@Override
public void doKickout(String loginType, Object loginId, String tokenValue) {
// ...
}
/** 每次被顶下线时触发 */
@Override
public void doReplaced(String loginType, Object loginId, String tokenValue) {
// ...
}
/** 每次被封禁时触发 */
@Override
public void doDisable(String loginType, Object loginId, long disableTime) {
// ...
}
/** 每次被解封时触发 */
@Override
public void doUntieDisable(String loginType, Object loginId) {
// ...
}
/** 每次创建Session时触发 */
@Override
public void doCreateSession(String id) {
// ...
}
/** 每次注销Session时触发 */
@Override
public void doLogoutSession(String id) {
// ...
}
}

View File

@ -0,0 +1,21 @@
package com.pj;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import cn.dev33.satoken.SaManager;
/**
* Sa-Token整合SpringBoot 示例整合redis
* @author kong
*
*/
@SpringBootApplication
public class SaTokenDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SaTokenDemoApplication.class, args);
System.out.println("\n启动成功Sa-Token配置如下" + SaManager.getConfig());
}
}

View File

@ -0,0 +1,57 @@
package com.pj.current;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import com.pj.util.AjaxJson;
import cn.dev33.satoken.exception.DisableLoginException;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
/**
* 全局异常处理
*/
@RestControllerAdvice
public class GlobalException {
// 全局异常拦截拦截项目中的所有异常
@ExceptionHandler
public AjaxJson handlerException(Exception e, HttpServletRequest request, HttpServletResponse response)
throws Exception {
// 打印堆栈以供调试
System.out.println("全局异常---------------");
e.printStackTrace();
// 不同异常返回不同状态码
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 DisableLoginException) { // 如果是被封禁异常
DisableLoginException ee = (DisableLoginException) e;
aj = AjaxJson.getNotJur("账号被封禁:" + ee.getDisableTime() + "秒后解封");
}
else { // 普通异常, 输出500 + 异常信息
aj = AjaxJson.getError(e.getMessage());
}
// 返回给前端
return aj;
}
}

View File

@ -0,0 +1,27 @@
package com.pj.current;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import cn.dev33.satoken.util.SaResult;
/**
* 处理 404
* @author kong
*/
@RestController
public class NotFoundHandle implements ErrorController {
@RequestMapping("/error")
public Object error(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setStatus(200);
return SaResult.get(404, "not found", null);
}
}

View File

@ -0,0 +1,85 @@
package com.pj.satoken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.pj.util.AjaxJson;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;
import cn.dev33.satoken.strategy.SaStrategy;
/**
* [Sa-Token 权限认证] 配置类
* @author kong
*
*/
@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
/**
* 注册Sa-Token 的拦截器打开注解式鉴权功能
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册注解拦截器
registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**");
}
/**
* 注册 [Sa-Token 全局过滤器]
*/
@Bean
public SaServletFilter getSaServletFilter() {
return new SaServletFilter()
// 指定 [拦截路由] [放行路由]
.addInclude("/**")// .addExclude("/favicon.ico")
// 认证函数: 每次请求执行
.setAuth(obj -> {
// System.out.println("---------- sa全局认证 " + SaHolder.getRequest().getRequestPath());
})
// 异常处理函数每次认证函数发生异常时执行此函数
.setError(e -> {
System.out.println("---------- sa全局异常 ");
return AjaxJson.getError(e.getMessage());
})
// 前置函数在每次认证函数之前执行
.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-XSS-Protection", "1; mode=block")
// 禁用浏览器内容嗅探
.setHeader("X-Content-Type-Options", "nosniff")
;
})
;
}
/**
* 重写 Sa-Token 框架内部算法策略
*/
@Autowired
public void rewriteSaStrategy() {
// 重写Sa-Token的注解处理器增加注解合并功能
SaStrategy.me.getAnnotation = (element, annotationClass) -> {
return AnnotatedElementUtils.getMergedAnnotation(element, annotationClass);
};
}
}

View File

@ -0,0 +1,44 @@
package com.pj.satoken;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Component;
import cn.dev33.satoken.stp.StpInterface;
/**
* 自定义权限验证接口扩展
*/
@Component // 打开此注解保证此类被springboot扫描即可完成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;
}
}

View File

@ -0,0 +1,21 @@
package com.pj.satoken.at;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import cn.dev33.satoken.annotation.SaCheckLogin;
/**
* 登录认证(User版)只有登录之后才能进入该方法
* <p> 可标注在函数类上效果等同于标注在此类的所有方法上
* @author kong
*
*/
@SaCheckLogin(type = StpUserUtil.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE})
public @interface SaUserCheckLogin {
}

View File

@ -0,0 +1,38 @@
package com.pj.satoken.at;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaMode;
/**
* 权限认证(User版)必须具有指定权限才能进入该方法
* <p> 可标注在函数类上效果等同于标注在此类的所有方法上
* @author kong
*
*/
@SaCheckPermission(type = StpUserUtil.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE})
public @interface SaUserCheckPermission {
/**
* 需要校验的权限码
* @return 需要校验的权限码
*/
@AliasFor(annotation = SaCheckPermission.class)
String [] value() default {};
/**
* 验证模式AND | OR默认AND
* @return 验证模式
*/
@AliasFor(annotation = SaCheckPermission.class)
SaMode mode() default SaMode.AND;
}

View File

@ -0,0 +1,38 @@
package com.pj.satoken.at;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaMode;
/**
* 角色认证(User版)必须具有指定角色标识才能进入该方法
* <p> 可标注在函数类上效果等同于标注在此类的所有方法上
* @author kong
*
*/
@SaCheckRole(type = StpUserUtil.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE})
public @interface SaUserCheckRole {
/**
* 需要校验的角色标识
* @return 需要校验的角色标识
*/
@AliasFor(annotation = SaCheckRole.class)
String [] value() default {};
/**
* 验证模式AND | OR默认AND
* @return 验证模式
*/
@AliasFor(annotation = SaCheckRole.class)
SaMode mode() default SaMode.AND;
}

View File

@ -0,0 +1,912 @@
package com.pj.satoken.at;
import java.util.List;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.fun.SaFunction;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
/**
* Sa-Token 权限认证工具类 (user版)
* @author kong
*/
public class StpUserUtil {
/**
* 账号类型标识
*/
public static final String TYPE = "user";
/**
* 底层的 StpLogic 对象
*/
public static StpLogic stpLogic = new StpLogic(TYPE);
/**
* 获取当前 StpLogic 的账号类型
* @return See Note
*/
public static String getLoginType(){
return stpLogic.getLoginType();
}
/**
* 重置 StpLogic 对象
* @param stpLogic /
*/
public static void setStpLogic(StpLogic stpLogic) {
StpUtil.stpLogic = stpLogic;
// 防止自定义 stpLogic 被覆盖
SaManager.putStpLogic(stpLogic);
}
// =================== 获取token 相关 ===================
/**
* 返回token名称
* @return 此StpLogic的token名称
*/
public static String getTokenName() {
return stpLogic.getTokenName();
}
/**
* 在当前会话写入当前TokenValue
* @param tokenValue token值
*/
public static void setTokenValue(String tokenValue){
stpLogic.setTokenValue(tokenValue);
}
/**
* 在当前会话写入当前TokenValue
* @param tokenValue token值
* @param cookieTimeout Cookie存活时间()
*/
public static void setTokenValue(String tokenValue, int cookieTimeout){
stpLogic.setTokenValue(tokenValue, cookieTimeout);
}
/**
* 获取当前TokenValue
* @return 当前tokenValue
*/
public static String getTokenValue() {
return stpLogic.getTokenValue();
}
/**
* 获取当前TokenValue (不裁剪前缀)
* @return /
*/
public static String getTokenValueNotCut(){
return stpLogic.getTokenValueNotCut();
}
/**
* 获取当前会话的Token信息
* @return token信息
*/
public static SaTokenInfo getTokenInfo() {
return stpLogic.getTokenInfo();
}
// =================== 登录相关操作 ===================
// --- 登录
/**
* 会话登录
* @param id 账号id建议的类型long | int | String
*/
public static void login(Object id) {
stpLogic.login(id);
}
/**
* 会话登录并指定登录设备类型
* @param id 账号id建议的类型long | int | String
* @param device 设备类型
*/
public static void login(Object id, String device) {
stpLogic.login(id, device);
}
/**
* 会话登录并指定是否 [记住我]
* @param id 账号id建议的类型long | int | String
* @param isLastingCookie 是否为持久Cookie
*/
public static void login(Object id, boolean isLastingCookie) {
stpLogic.login(id, isLastingCookie);
}
/**
* 会话登录并指定所有登录参数Model
* @param id 登录id建议的类型long | int | String
* @param loginModel 此次登录的参数Model
*/
public static void login(Object id, SaLoginModel loginModel) {
stpLogic.login(id, loginModel);
}
/**
* 创建指定账号id的登录会话
* @param id 登录id建议的类型long | int | String
* @return 返回会话令牌
*/
public static String createLoginSession(Object id) {
return stpLogic.createLoginSession(id);
}
/**
* 创建指定账号id的登录会话
* @param id 登录id建议的类型long | int | String
* @param loginModel 此次登录的参数Model
* @return 返回会话令牌
*/
public static String createLoginSession(Object id, SaLoginModel loginModel) {
return stpLogic.createLoginSession(id, loginModel);
}
// --- 注销
/**
* 会话注销
*/
public static void logout() {
stpLogic.logout();
}
/**
* 会话注销根据账号id
* @param loginId 账号id
*/
public static void logout(Object loginId) {
stpLogic.logout(loginId);
}
/**
* 会话注销根据账号id 设备类型
*
* @param loginId 账号id
* @param device 设备类型 (填null代表注销所有设备类型)
*/
public static void logout(Object loginId, String device) {
stpLogic.logout(loginId, device);
}
/**
* 会话注销根据指定 Token
*
* @param tokenValue 指定token
*/
public static void logoutByTokenValue(String tokenValue) {
stpLogic.logoutByTokenValue(tokenValue);
}
/**
* 踢人下线根据账号id
* <p> 当对方再次访问系统时会抛出NotLoginException异常场景值=-5 </p>
*
* @param loginId 账号id
*/
public static void kickout(Object loginId) {
stpLogic.kickout(loginId);
}
/**
* 踢人下线根据账号id 设备类型
* <p> 当对方再次访问系统时会抛出NotLoginException异常场景值=-5 </p>
*
* @param loginId 账号id
* @param device 设备类型 (填null代表踢出所有设备类型)
*/
public static void kickout(Object loginId, String device) {
stpLogic.kickout(loginId, device);
}
/**
* 踢人下线根据指定 Token
* <p> 当对方再次访问系统时会抛出NotLoginException异常场景值=-5 </p>
*
* @param tokenValue 指定token
*/
public static void kickoutByTokenValue(String tokenValue) {
stpLogic.kickoutByTokenValue(tokenValue);
}
/**
* 顶人下线根据账号id 设备类型
* <p> 当对方再次访问系统时会抛出NotLoginException异常场景值=-4 </p>
*
* @param loginId 账号id
* @param device 设备类型 (填null代表顶替所有设备类型)
*/
public static void replaced(Object loginId, String device) {
stpLogic.replaced(loginId, device);
}
// 查询相关
/**
* 当前会话是否已经登录
* @return 是否已登录
*/
public static boolean isLogin() {
return stpLogic.isLogin();
}
/**
* 检验当前会话是否已经登录如未登录则抛出异常
*/
public static void checkLogin() {
stpLogic.checkLogin();
}
/**
* 获取当前会话账号id, 如果未登录则抛出异常
* @return 账号id
*/
public static Object getLoginId() {
return stpLogic.getLoginId();
}
/**
* 获取当前会话账号id, 如果未登录则返回默认值
* @param <T> 返回类型
* @param defaultValue 默认值
* @return 登录id
*/
public static <T> T getLoginId(T defaultValue) {
return stpLogic.getLoginId(defaultValue);
}
/**
* 获取当前会话账号id, 如果未登录则返回null
* @return 账号id
*/
public static Object getLoginIdDefaultNull() {
return stpLogic.getLoginIdDefaultNull();
}
/**
* 获取当前会话账号id, 并转换为String类型
* @return 账号id
*/
public static String getLoginIdAsString() {
return stpLogic.getLoginIdAsString();
}
/**
* 获取当前会话账号id, 并转换为int类型
* @return 账号id
*/
public static int getLoginIdAsInt() {
return stpLogic.getLoginIdAsInt();
}
/**
* 获取当前会话账号id, 并转换为long类型
* @return 账号id
*/
public static long getLoginIdAsLong() {
return stpLogic.getLoginIdAsLong();
}
/**
* 获取指定Token对应的账号id如果未登录则返回 null
* @param tokenValue token
* @return 账号id
*/
public static Object getLoginIdByToken(String tokenValue) {
return stpLogic.getLoginIdByToken(tokenValue);
}
/**
* 获取Token扩展信息只在jwt模式下有效
* @param key 键值
* @return 对应的扩展数据
*/
public static Object getExtra(String key) {
return stpLogic.getExtra(key);
}
// =================== User-Session 相关 ===================
/**
* 获取指定账号id的Session, 如果Session尚未创建isCreate=是否新建并返回
* @param loginId 账号id
* @param isCreate 是否新建
* @return Session对象
*/
public static SaSession getSessionByLoginId(Object loginId, boolean isCreate) {
return stpLogic.getSessionByLoginId(loginId, isCreate);
}
/**
* 获取指定key的Session, 如果Session尚未创建则返回null
* @param sessionId SessionId
* @return Session对象
*/
public static SaSession getSessionBySessionId(String sessionId) {
return stpLogic.getSessionBySessionId(sessionId);
}
/**
* 获取指定账号id的Session如果Session尚未创建则新建并返回
* @param loginId 账号id
* @return Session对象
*/
public static SaSession getSessionByLoginId(Object loginId) {
return stpLogic.getSessionByLoginId(loginId);
}
/**
* 获取当前会话的Session, 如果Session尚未创建isCreate=是否新建并返回
* @param isCreate 是否新建
* @return Session对象
*/
public static SaSession getSession(boolean isCreate) {
return stpLogic.getSession(isCreate);
}
/**
* 获取当前会话的Session如果Session尚未创建则新建并返回
* @return Session对象
*/
public static SaSession getSession() {
return stpLogic.getSession();
}
// =================== Token-Session 相关 ===================
/**
* 获取指定Token-Session如果Session尚未创建则新建并返回
* @param tokenValue Token值
* @return Session对象
*/
public static SaSession getTokenSessionByToken(String tokenValue) {
return stpLogic.getTokenSessionByToken(tokenValue);
}
/**
* 获取当前Token-Session如果Session尚未创建则新建并返回
* @return Session对象
*/
public static SaSession getTokenSession() {
return stpLogic.getTokenSession();
}
// =================== [临时有效期] 验证相关 ===================
/**
* 检查当前token 是否已经[临时过期]如果已经过期则抛出异常
*/
public static void checkActivityTimeout() {
stpLogic.checkActivityTimeout();
}
/**
* 续签当前token( [最后操作时间] 更新为当前时间戳)
* <h1>请注意: 即使token已经 [临时过期] 也可续签成功
* 如果此场景下需要提示续签失败可在此之前调用 checkActivityTimeout() 强制检查是否过期即可 </h1>
*/
public static void updateLastActivityToNow() {
stpLogic.updateLastActivityToNow();
}
// =================== 过期时间相关 ===================
/**
* 获取当前登录者的 token 剩余有效时间 (单位: )
* @return token剩余有效时间
*/
public static long getTokenTimeout() {
return stpLogic.getTokenTimeout();
}
/**
* 获取当前登录者的 User-Session 剩余有效时间 (单位: )
* @return token剩余有效时间
*/
public static long getSessionTimeout() {
return stpLogic.getSessionTimeout();
}
/**
* 获取当前 Token-Session 剩余有效时间 (单位: )
* @return token剩余有效时间
*/
public static long getTokenSessionTimeout() {
return stpLogic.getTokenSessionTimeout();
}
/**
* 获取当前 token [临时过期] 剩余有效时间 (单位: )
* @return token [临时过期] 剩余有效时间
*/
public static long getTokenActivityTimeout() {
return stpLogic.getTokenActivityTimeout();
}
/**
* 对当前 Token timeout 值进行续期
* @param timeout 要修改成为的有效时间 (单位: )
*/
public static void renewTimeout(long timeout) {
stpLogic.renewTimeout(timeout);
}
/**
* 对指定 Token timeout 值进行续期
* @param tokenValue 指定token
* @param timeout 要修改成为的有效时间 (单位: )
*/
public static void renewTimeout(String tokenValue, long timeout) {
stpLogic.renewTimeout(tokenValue, timeout);
}
// =================== 角色验证操作 ===================
/**
* 获取当前账号的角色集合
* @return /
*/
public static List<String> getRoleList() {
return stpLogic.getRoleList();
}
/**
* 获取指定账号的角色集合
* @param loginId 指定账号id
* @return /
*/
public static List<String> getRoleList(Object loginId) {
return stpLogic.getRoleList(loginId);
}
/**
* 判断当前账号是否拥有指定角色, 返回true或false
* @param role 角色标识
* @return 是否含有指定角色标识
*/
public static boolean hasRole(String role) {
return stpLogic.hasRole(role);
}
/**
* 判断指定账号是否含有指定角色标识, 返回true或false
* @param loginId 账号id
* @param role 角色标识
* @return 是否含有指定角色标识
*/
public static boolean hasRole(Object loginId, String role) {
return stpLogic.hasRole(loginId, role);
}
/**
* 判断当前账号是否含有指定角色标识 [指定多个必须全部验证通过]
* @param roleArray 角色标识数组
* @return true或false
*/
public static boolean hasRoleAnd(String... roleArray){
return stpLogic.hasRoleAnd(roleArray);
}
/**
* 判断当前账号是否含有指定角色标识 [指定多个只要其一验证通过即可]
* @param roleArray 角色标识数组
* @return true或false
*/
public static boolean hasRoleOr(String... roleArray){
return stpLogic.hasRoleOr(roleArray);
}
/**
* 校验当前账号是否含有指定角色标识, 如果验证未通过则抛出异常: NotRoleException
* @param role 角色标识
*/
public static void checkRole(String role) {
stpLogic.checkRole(role);
}
/**
* 校验当前账号是否含有指定角色标识 [指定多个必须全部验证通过]
* @param roleArray 角色标识数组
*/
public static void checkRoleAnd(String... roleArray){
stpLogic.checkRoleAnd(roleArray);
}
/**
* 校验当前账号是否含有指定角色标识 [指定多个只要其一验证通过即可]
* @param roleArray 角色标识数组
*/
public static void checkRoleOr(String... roleArray){
stpLogic.checkRoleOr(roleArray);
}
// =================== 权限验证操作 ===================
/**
* 获取当前账号的权限码集合
* @return /
*/
public static List<String> getPermissionList() {
return stpLogic.getPermissionList();
}
/**
* 获取指定账号的权限码集合
* @param loginId 指定账号id
* @return /
*/
public static List<String> getPermissionList(Object loginId) {
return stpLogic.getPermissionList(loginId);
}
/**
* 判断当前账号是否含有指定权限, 返回true或false
* @param permission 权限码
* @return 是否含有指定权限
*/
public static boolean hasPermission(String permission) {
return stpLogic.hasPermission(permission);
}
/**
* 判断指定账号id是否含有指定权限, 返回true或false
* @param loginId 账号id
* @param permission 权限码
* @return 是否含有指定权限
*/
public static boolean hasPermission(Object loginId, String permission) {
return stpLogic.hasPermission(loginId, permission);
}
/**
* 判断当前账号是否含有指定权限, [指定多个必须全部具有]
* @param permissionArray 权限码数组
* @return true false
*/
public static boolean hasPermissionAnd(String... permissionArray){
return stpLogic.hasPermissionAnd(permissionArray);
}
/**
* 判断当前账号是否含有指定权限 [指定多个只要其一验证通过即可]
* @param permissionArray 权限码数组
* @return true false
*/
public static boolean hasPermissionOr(String... permissionArray){
return stpLogic.hasPermissionOr(permissionArray);
}
/**
* 校验当前账号是否含有指定权限, 如果验证未通过则抛出异常: NotPermissionException
* @param permission 权限码
*/
public static void checkPermission(String permission) {
stpLogic.checkPermission(permission);
}
/**
* 校验当前账号是否含有指定权限 [指定多个必须全部验证通过]
* @param permissionArray 权限码数组
*/
public static void checkPermissionAnd(String... permissionArray) {
stpLogic.checkPermissionAnd(permissionArray);
}
/**
* 校验当前账号是否含有指定权限 [指定多个只要其一验证通过即可]
* @param permissionArray 权限码数组
*/
public static void checkPermissionOr(String... permissionArray) {
stpLogic.checkPermissionOr(permissionArray);
}
// =================== id 反查token 相关操作 ===================
/**
* 获取指定账号id的tokenValue
* <p> 在配置为允许并发登录时此方法只会返回队列的最后一个token
* 如果你需要返回此账号id的所有token请调用 getTokenValueListByLoginId
* @param loginId 账号id
* @return token值
*/
public static String getTokenValueByLoginId(Object loginId) {
return stpLogic.getTokenValueByLoginId(loginId);
}
/**
* 获取指定账号id指定设备类型端的tokenValue
* <p> 在配置为允许并发登录时此方法只会返回队列的最后一个token
* 如果你需要返回此账号id的所有token请调用 getTokenValueListByLoginId
* @param loginId 账号id
* @param device 设备类型
* @return token值
*/
public static String getTokenValueByLoginId(Object loginId, String device) {
return stpLogic.getTokenValueByLoginId(loginId, device);
}
/**
* 获取指定账号id的tokenValue集合
* @param loginId 账号id
* @return 此loginId的所有相关token
*/
public static List<String> getTokenValueListByLoginId(Object loginId) {
return stpLogic.getTokenValueListByLoginId(loginId);
}
/**
* 获取指定账号id指定设备类型端的tokenValue 集合
* @param loginId 账号id
* @param device 设备类型
* @return 此loginId的所有相关token
*/
public static List<String> getTokenValueListByLoginId(Object loginId, String device) {
return stpLogic.getTokenValueListByLoginId(loginId, device);
}
/**
* 返回当前会话的登录设备类型
* @return 当前令牌的登录设备类型
*/
public static String getLoginDevice() {
return stpLogic.getLoginDevice();
}
// =================== 会话管理 ===================
/**
* 根据条件查询Token
* @param keyword 关键字
* @param start 开始处索引 (-1代表查询所有)
* @param size 获取数量
* @return token集合
*/
public static List<String> searchTokenValue(String keyword, int start, int size) {
return stpLogic.searchTokenValue(keyword, start, size);
}
/**
* 根据条件查询SessionId
* @param keyword 关键字
* @param start 开始处索引 (-1代表查询所有)
* @param size 获取数量
* @return sessionId集合
*/
public static List<String> searchSessionId(String keyword, int start, int size) {
return stpLogic.searchSessionId(keyword, start, size);
}
/**
* 根据条件查询Token专属Session的Id
* @param keyword 关键字
* @param start 开始处索引 (-1代表查询所有)
* @param size 获取数量
* @return sessionId集合
*/
public static List<String> searchTokenSessionId(String keyword, int start, int size) {
return stpLogic.searchTokenSessionId(keyword, start, size);
}
// ------------------- 账号封禁 -------------------
/**
* 封禁指定账号
* <p> 此方法不会直接将此账号id踢下线而是在对方再次登录时抛出`DisableLoginException`异常
* @param loginId 指定账号id
* @param disableTime 封禁时间, 单位: -1=永久封禁
*/
public static void disable(Object loginId, long disableTime) {
stpLogic.disable(loginId, disableTime);
}
/**
* 指定账号是否已被封禁 (true=已被封禁, false=未被封禁)
* @param loginId 账号id
* @return see note
*/
public static boolean isDisable(Object loginId) {
return stpLogic.isDisable(loginId);
}
/**
* 获取指定账号剩余封禁时间单位-1=永久封禁-2=未被封禁
* @param loginId 账号id
* @return see note
*/
public static long getDisableTime(Object loginId) {
return stpLogic.getDisableTime(loginId);
}
/**
* 解封指定账号
* @param loginId 账号id
*/
public static void untieDisable(Object loginId) {
stpLogic.untieDisable(loginId);
}
// =================== 身份切换 ===================
/**
* 临时切换身份为指定账号id
* @param loginId 指定loginId
*/
public static void switchTo(Object loginId) {
stpLogic.switchTo(loginId);
}
/**
* 结束临时切换身份
*/
public static void endSwitch() {
stpLogic.endSwitch();
}
/**
* 当前是否正处于[身份临时切换]
* @return 是否正处于[身份临时切换]
*/
public static boolean isSwitch() {
return stpLogic.isSwitch();
}
/**
* 在一个代码段里方法内临时切换身份为指定账号id
* @param loginId 指定账号id
* @param function 要执行的方法
*/
public static void switchTo(Object loginId, SaFunction function) {
stpLogic.switchTo(loginId, function);
}
// ------------------- 二级认证 -------------------
/**
* 在当前会话 开启二级认证
* @param safeTime 维持时间 (单位: )
*/
public static void openSafe(long safeTime) {
stpLogic.openSafe(safeTime);
}
/**
* 当前会话 是否处于二级认证时间内
* @return true=二级认证已通过, false=尚未进行二级认证或认证已超时
*/
public static boolean isSafe() {
return stpLogic.isSafe();
}
/**
* 检查当前会话是否已通过二级认证如未通过则抛出异常
*/
public static void checkSafe() {
stpLogic.checkSafe();
}
/**
* 获取当前会话的二级认证剩余有效时间 (单位: , 返回-2代表尚未通过二级认证)
* @return 剩余有效时间
*/
public static long getSafeTime() {
return stpLogic.getSafeTime();
}
/**
* 在当前会话 结束二级认证
*/
public static void closeSafe() {
stpLogic.closeSafe();
}
// =================== 历史API兼容旧版本 ===================
/**
* <h1> 本函数设计已过时未来版本可能移除此函数请及时更换为 StpUtil.getLoginType() 使用方式保持不变 </h1>
*
* 获取当前StpLogin的loginKey
* @return 当前StpLogin的loginKey
*/
@Deprecated
public static String getLoginKey(){
return stpLogic.getLoginType();
}
/**
* <h1> 本函数设计已过时未来版本可能移除此函数请及时更换为 StpUtil.login() 使用方式保持不变 </h1>
*
* 在当前会话上登录id
* @param loginId 登录id建议的类型long | int | String
*/
@Deprecated
public static void setLoginId(Object loginId) {
stpLogic.login(loginId);
}
/**
* <h1> 本函数设计已过时未来版本可能移除此函数请及时更换为 StpUtil.login() 使用方式保持不变 </h1>
*
* 在当前会话上登录id, 并指定登录设备类型
* @param loginId 登录id建议的类型long | int | String
* @param device 设备类型
*/
@Deprecated
public static void setLoginId(Object loginId, String device) {
stpLogic.login(loginId, device);
}
/**
* <h1> 本函数设计已过时未来版本可能移除此函数请及时更换为 StpUtil.login() 使用方式保持不变 </h1>
*
* 在当前会话上登录id, 并指定登录设备类型
* @param loginId 登录id建议的类型long | int | String
* @param isLastingCookie 是否为持久Cookie
*/
@Deprecated
public static void setLoginId(Object loginId, boolean isLastingCookie) {
stpLogic.login(loginId, isLastingCookie);
}
/**
* <h1> 本函数设计已过时未来版本可能移除此函数请及时更换为 StpUtil.login() 使用方式保持不变 </h1>
*
* 在当前会话上登录id, 并指定所有登录参数Model
* @param loginId 登录id建议的类型long | int | String
* @param loginModel 此次登录的参数Model
*/
@Deprecated
public static void setLoginId(Object loginId, SaLoginModel loginModel) {
stpLogic.login(loginId, loginModel);
}
/**
* <h1> 本函数设计已过时未来版本可能移除此函数请及时更换为 StpUtil.kickout() 使用方式保持不变 </h1>
*
* 会话注销根据账号id 踢人下线
* <p> 当对方再次访问系统时会抛出NotLoginException异常场景值=-2
* @param loginId 账号id
*/
@Deprecated
public static void logoutByLoginId(Object loginId) {
stpLogic.kickout(loginId);
}
/**
* <h1> 本函数设计已过时未来版本可能移除此函数请及时更换为 StpUtil.kickout() 使用方式保持不变 </h1>
*
* 会话注销根据账号id and 设备类型 踢人下线
* <p> 当对方再次访问系统时会抛出NotLoginException异常场景值=-2 </p>
* @param loginId 账号id
* @param device 设备类型 (填null代表注销所有设备类型)
*/
@Deprecated
public static void logoutByLoginId(Object loginId, String device) {
stpLogic.kickout(loginId, device);
}
}

View File

@ -0,0 +1,80 @@
package com.pj.test;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import cn.dev33.satoken.annotation.SaCheckBasic;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaCheckSafe;
import cn.dev33.satoken.annotation.SaMode;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
/**
* 注解鉴权测试
* @author kong
*
*/
@RestController
@RequestMapping("/at/")
public class AtController {
// 登录认证登录之后才可以进入方法 ---- http://localhost:8081/at/checkLogin
@SaCheckLogin
@RequestMapping("checkLogin")
public SaResult checkLogin() {
return SaResult.ok();
}
// 权限认证具备user-add权限才可以进入方法 ---- http://localhost:8081/at/checkPermission
@SaCheckPermission("user-add")
@RequestMapping("checkPermission")
public SaResult checkPermission() {
return SaResult.ok();
}
// 权限认证同时具备所有权限才可以进入 ---- http://localhost:8081/at/checkPermissionAnd
@SaCheckPermission({"user-add", "user-delete", "user-update"})
@RequestMapping("checkPermissionAnd")
public SaResult checkPermissionAnd() {
return SaResult.ok();
}
// 权限认证只要具备其中一个就可以进入 ---- http://localhost:8081/at/checkPermissionOr
@SaCheckPermission(value = {"user-add", "user-delete", "user-update"}, mode = SaMode.OR)
@RequestMapping("checkPermissionOr")
public SaResult checkPermissionOr() {
return SaResult.ok();
}
// 角色认证只有具备admin角色才可以进入 ---- http://localhost:8081/at/checkRole
@SaCheckRole("admin")
@RequestMapping("checkRole")
public SaResult checkRole() {
return SaResult.ok();
}
// 完成二级认证 ---- http://localhost:8081/at/openSafe
@RequestMapping("openSafe")
public SaResult openSafe() {
StpUtil.openSafe(200); // 打开二级认证有效期为200秒
return SaResult.ok();
}
// 通过二级认证后才可以进入 ---- http://localhost:8081/at/checkSafe
@SaCheckSafe
@RequestMapping("checkSafe")
public SaResult checkSafe() {
return SaResult.ok();
}
// 通过Basic认证后才可以进入 ---- http://localhost:8081/at/checkBasic
@SaCheckBasic(account = "sa:123456")
@RequestMapping("checkBasic")
public SaResult checkBasic() {
return SaResult.ok();
}
}

View File

@ -0,0 +1,48 @@
package com.pj.test;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
/**
* 登录测试
* @author kong
*
*/
@RestController
@RequestMapping("/acc/")
public class LoginController {
// 测试登录 ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456
@RequestMapping("doLogin")
public SaResult doLogin(String name, String pwd) {
// 此处仅作模拟示例真实项目需要从数据库中查询数据进行比对
if("zhang".equals(name) && "123456".equals(pwd)) {
StpUtil.login(10001);
return SaResult.ok("登录成功");
}
return SaResult.error("登录失败");
}
// 查询登录状态 ---- http://localhost:8081/acc/isLogin
@RequestMapping("isLogin")
public SaResult isLogin() {
return SaResult.ok("是否登录:" + StpUtil.isLogin());
}
// 查询 Token 信息 ---- http://localhost:8081/acc/tokenInfo
@RequestMapping("tokenInfo")
public SaResult tokenInfo() {
return SaResult.data(StpUtil.getTokenInfo());
}
// 测试注销 ---- http://localhost:8081/acc/logout
@RequestMapping("logout")
public SaResult logout() {
StpUtil.logout();
return SaResult.ok();
}
}

View File

@ -0,0 +1,61 @@
package com.pj.test;
import java.util.ArrayList;
import java.util.List;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.pj.util.AjaxJson;
import com.pj.util.Ttime;
import cn.dev33.satoken.stp.StpUtil;
/**
* 压力测试
* @author kong
*
*/
@RestController
@RequestMapping("/s-test/")
public class StressTestController {
// 测试 浏览器访问 http://localhost:8081/s-test/login
// 测试前请先将 is-read-cookie 配置为 false
@RequestMapping("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();
}
}

View File

@ -0,0 +1,251 @@
package com.pj.test;
import java.util.Date;
import java.util.List;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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;
/**
* 测试专用Controller
* @author kong
*
*/
@RestController
@RequestMapping("/test/")
public class TestController {
// 测试登录接口 浏览器访问 http://localhost:8081/test/login
@RequestMapping("login")
public AjaxJson login(@RequestParam(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
@RequestMapping("logout")
public AjaxJson logout() {
StpUtil.logout();
// StpUtil.logoutByLoginId(10001);
return AjaxJson.getSuccess();
}
// 测试角色接口 浏览器访问 http://localhost:8081/test/testRole
@RequestMapping("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
@RequestMapping("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
@RequestMapping("session")
public AjaxJson session() throws JsonProcessingException {
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( new ObjectMapper().writeValueAsString(StpUtil.getSession()));
return AjaxJson.getSuccess();
}
// 测试自定义session接口 浏览器访问 http://localhost:8081/test/session2
@RequestMapping("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
@RequestMapping("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
@RequestMapping("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") // 注解式鉴权当前会话必须具有指定权限才能通过
@RequestMapping("atCheck")
public AjaxJson atCheck() {
System.out.println("======================= 进入方法,测试注解鉴权接口 ========================= ");
System.out.println("只有通过注解鉴权,才能进入此方法");
// StpUtil.checkActivityTimeout();
// StpUtil.updateLastActivityToNow();
return AjaxJson.getSuccess();
}
// 测试注解式鉴权 浏览器访问 http://localhost:8081/test/atJurOr
@RequestMapping("atJurOr")
@SaCheckPermission(value = {"user-add", "user-all", "user-delete"}, mode = SaMode.OR) // 注解式鉴权只要具有其中一个权限即可通过校验
public AjaxJson atJurOr() {
return AjaxJson.getSuccessData("用户信息");
}
// [活动时间] 续签 http://localhost:8081/test/rene
@RequestMapping("rene")
public AjaxJson rene() {
StpUtil.checkActivityTimeout();
StpUtil.updateLastActivityToNow();
return AjaxJson.getSuccess("续签成功");
}
// 测试踢人下线 浏览器访问 http://localhost:8081/test/kickOut
@RequestMapping("kickOut")
public AjaxJson kickOut() {
// 先登录上
StpUtil.login(10001);
// 踢下线
StpUtil.kickout(10001);
// 再尝试获取
StpUtil.getLoginId();
// 返回
return AjaxJson.getSuccess();
}
// 测试登录接口, 按照设备登录 浏览器访问 http://localhost:8081/test/login2
@RequestMapping("login2")
public AjaxJson login2(@RequestParam(defaultValue="10001") String id, @RequestParam(defaultValue="PC") String device) {
StpUtil.login(id, device);
return AjaxJson.getSuccess();
}
// 测试身份临时切换 http://localhost:8081/test/switchTo
@RequestMapping("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
@RequestMapping("search")
public AjaxJson search() {
System.out.println("--------------");
Ttime t = new Ttime().start();
List<String> tokenValue = StpUtil.searchTokenValue("8feb8265f773", 0, 10);
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
@RequestMapping("loginByDevice")
public AjaxJson loginByDevice() {
System.out.println("--------------");
StpUtil.login(10001, "PC");
return AjaxJson.getSuccessData("登录成功");
}
// 测试 浏览器访问 http://localhost:8081/test/test
@RequestMapping("test")
public AjaxJson test() {
System.out.println("------------进来了");
return AjaxJson.getSuccess();
}
// 测试 浏览器访问 http://localhost:8081/test/test2
@RequestMapping("test2")
public AjaxJson test2() {
return AjaxJson.getSuccess();
}
}

View File

@ -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=okfalse=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
+ "}";
}
}

View File

@ -0,0 +1,63 @@
package com.pj.util;
/**
* 用于测试用时
* @author kong
*
*/
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
}
}

View File

@ -0,0 +1,49 @@
# 端口
server:
port: 8081
# sa-token配置
sa-token:
# token名称 (同时也是cookie名称)
token-name: satoken
# token有效期单位s 默认30天, -1代表永不过期
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: true
# token风格
token-style: uuid
# 是否输出操作日志
is-log: false
spring:
# redis配置
redis:
# Redis数据库索引默认为0
database: 0
# Redis服务器地址
host: 127.0.0.1
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码默认为空
password:
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池最大连接数
max-active: 200
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# 连接池中的最大空闲连接
max-idle: 10
# 连接池中的最小空闲连接
min-idle: 0