提交 3329910b 编写于 作者: shengzhang_'s avatar shengzhang_

第一版

上级 9a372b74
# sa-token
一个好用的JavaWeb权限认证框架
在线文档:[http://sa-token.dev33.cn/](http://sa-token.dev33.cn/)
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
target/
node_modules/
bin/
.settings/
unpackage/
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>sa-token-demo-springboot</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>
<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</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- SpringBoot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<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 安全认证 -->
<dependency>
<groupId>cn.dev33.sa-token</groupId>
<artifactId>sa-token-spring</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/sa-token-spring-1.0.0.jar</systemPath>
</dependency>
<!-- SpringBoot整合redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies>
<!-- 配置打包 -->
<build>
<plugins>
<!-- 打包jar文件时,配置manifest文件,加入lib包的jar依赖 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.pj.SaTokenDemoApplication</mainClass>
</manifest>
<!-- jar清单添加此字符串 -->
<manifestEntries>
<Class-Path>lib/sa-token-spring-1.0.0.jar</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
<!-- 拷贝依赖的jar包到lib目录 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/lib
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package com.pj;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.fasterxml.jackson.core.JsonProcessingException;
import cn.dev33.satoken.spring.SaTokenSetup;
@SaTokenSetup // 标注启动 sa-token
@SpringBootApplication
public class SaTokenDemoApplication {
public static void main(String[] args) throws JsonProcessingException {
SpringApplication.run(SaTokenDemoApplication.class, args); // run-->
}
}
\ No newline at end of file
package com.pj.satoken;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
// import org.springframework.stereotype.Component;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.session.SaSession;
/**
* sa-token持久层的实现类 , 基于redis
*/
// @Component // 打开此注解,保证此类被springboot扫描,即可完成sa-token与redis的集成
public class SaTokenDaoRedis implements SaTokenDao {
// string专用
@Autowired
StringRedisTemplate stringRedisTemplate;
// SaSession专用
RedisTemplate<String, SaSession> redisTemplate;
@Autowired
@SuppressWarnings({ "rawtypes", "unchecked" })
public void setRedisTemplate(RedisTemplate redisTemplate) {
RedisSerializer stringSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringSerializer);
this.redisTemplate = redisTemplate;
}
// 根据key获取value ,如果没有,则返回空
@Override
public String getValue(String key) {
return stringRedisTemplate.opsForValue().get(key);
}
// 写入指定key-value键值对,并设定过期时间(单位:秒)
@Override
public void setValue(String key, String value, long timeout) {
stringRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
}
// 删除一个指定的key
@Override
public void delKey(String key) {
stringRedisTemplate.delete(key);
}
// 根据指定key的session,如果没有,则返回空
@Override
public SaSession getSaSession(String sessionId) {
return redisTemplate.opsForValue().get(sessionId);
}
// 将指定session持久化
@Override
public void saveSaSession(SaSession session, long timeout) {
redisTemplate.opsForValue().set(session.getId(), session, timeout, TimeUnit.SECONDS);
}
// 更新指定session
@Override
public void updateSaSession(SaSession session) {
long expire = redisTemplate.getExpire(session.getId());
if(expire == -2) { // -2 = 无此键
return;
}
redisTemplate.opsForValue().set(session.getId(), session, expire, TimeUnit.SECONDS);
}
// 删除一个指定的session
@Override
public void delSaSession(String sessionId) {
redisTemplate.delete(sessionId);
}
}
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 StpCustom implements StpInterface {
@Override
public List<Object> getPermissionCodeList(Object login_id, String login_key) {
List<Object> list = new ArrayList<Object>();
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;
}
}
package com.pj.test;
import java.io.Serializable;
import java.util.List;
/**
* ajax返回Json的封装
* 【此类封装了Meta和Body的功能,写法不同,但是返回数据格式相同】
*/
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
+ "}";
}
}
package com.pj.test;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import cn.dev33.satoken.session.SaSessionUtil;
import cn.dev33.satoken.stp.StpUtil;
@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.getLoginId_defaultNull());
StpUtil.setLoginId(id); // 在当前会话登录此账号
System.out.println("登录成功");
System.out.println("当前是否登录:" + StpUtil.isLogin());
System.out.println("当前登录账号:" + StpUtil.getLoginId());
System.out.println("当前登录账号:" + StpUtil.getLoginId_asInt()); // 获取登录id并转为int
System.out.println("当前token信息:" + StpUtil.getTokenInfo()); // 获取登录id并转为int
return AjaxJson.getSuccess();
}
// 测试权限接口, 浏览器访问: http://localhost:8081/test/jur
@RequestMapping("jur")
public AjaxJson jur() {
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() {
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().getAttribute("name"));
StpUtil.getSession().setAttribute("name", "张三"); // 写入一个值
System.out.println("测试取值name:" + StpUtil.getSession().getAttribute("name"));
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为:" + SaSessionUtil.getSessionById("1895544896").getId());
System.out.println("测试取值name:" + SaSessionUtil.getSessionById("1895544896").getAttribute("name"));
SaSessionUtil.getSessionById("1895544896").setAttribute("name", "张三"); // 写入值
System.out.println("测试取值name:" + SaSessionUtil.getSessionById("1895544896").getAttribute("name"));
System.out.println("测试取值name:" + SaSessionUtil.getSessionById("1895544896").getAttribute("name"));
return AjaxJson.getSuccess();
}
}
package com.pj.test;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import com.fasterxml.jackson.databind.ObjectMapper;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
/**
* 加强版控制器
*/
@ControllerAdvice // 可指定包前缀,比如:(basePackages = "com.zyd.blog.controller.admin")
public class TopController {
// 在每个控制器之前触发的操作
@ModelAttribute
public void get(HttpServletRequest request) throws IOException {
}
// 全局异常拦截(拦截项目中的所有异常)
@ExceptionHandler
public void handlerException(Exception e, HttpServletRequest request, HttpServletResponse response)
throws Exception {
e.printStackTrace(); // 打印堆栈,以供调试
response.setContentType("application/json; charset=utf-8"); // http说明,我要返回JSON对象
// 如果是未登录异常
if (e instanceof NotLoginException) {
String jsonStr = new ObjectMapper().writeValueAsString(AjaxJson.getNotLogin());
response.getWriter().print(jsonStr);
return;
}
// 如果是权限异常
if (e instanceof NotPermissionException) {
NotPermissionException ee = (NotPermissionException) e;
String jsonStr = new ObjectMapper().writeValueAsString(AjaxJson.getNotJur("无此权限:" + ee.getCode()));
response.getWriter().print(jsonStr);
return;
}
// 普通异常输出:500 + 异常信息
response.getWriter().print(new ObjectMapper().writeValueAsString(AjaxJson.getError(e.getMessage())));
}
}
# 端口
server:
port: 8081
spring:
# sa-token配置
sa-token:
# token名称(同时也是cookie名称)
token-name: satoken
# token有效期,单位s 默认30天,-1为永不过期
timeout: 2592000
# 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录)
is-share: true
# 是否在cookie读取不到token时,继续从请求header里继续尝试读取
is-read-head: true
# 是否在header读取不到token时,继续从请求题参数里继续尝试读取
is-read-body: true
# 是否在初始化配置时打印版本字符画
is-v: true
# redis配置
redis:
# Redis数据库索引(默认为0)
database: 1
# Redis服务器地址
host: 127.0.0.1
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码(默认为空)
password:
# 连接池最大连接数(使用负值表示没有限制)
pool:
maxActive: 20
# 连接池最大阻塞等待时间(使用负值表示没有限制)
maxWait: -1
# 连接池中的最大空闲连接
maxIdle: 8
# 连接池中的最小空闲连接
minIdle: 1
# 连接超时时间(毫秒)
timeout: 0
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
target/
node_modules/
bin/
.settings/
unpackage/
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>sa-token-dev</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>
<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-dev</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- SpringBoot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<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>
</dependencies>
</project>
\ No newline at end of file
package cn.dev33.satoken;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.config.SaTokenConfigFactory;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.dao.SaTokenDaoDefault;
import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpInterfaceDefaultImpl;
/**
* 管理sa-token所有对象
* @author kong
*
*/
public class SaTokenManager {
// 配置文件 Bean
private static SaTokenConfig config;
public static SaTokenConfig getConfig() {
if (config == null) {
initConfig();
}
return config;
}
public static void setConfig(SaTokenConfig config) {
SaTokenManager.config = config;
if(config.getIsV()) {
SaTokenUtil.printSaToken();
}
}
public synchronized static void initConfig() {
if (config == null) {
setConfig(SaTokenConfigFactory.createConfig());
}
}
// 持久化 Bean
public static SaTokenDao dao;
public static SaTokenDao getDao() {
if (dao == null) {
initDao();
}
return dao;
}
public static void setDao(SaTokenDao dao) {
SaTokenManager.dao = dao;
}
public synchronized static void initDao() {
if (dao == null) {
setDao(new SaTokenDaoDefault());
}
}
// 权限认证 Bean
public static StpInterface stp;
public static StpInterface getStp() {
if (stp == null) {
initStp();
}
return stp;
}
public static void setStp(StpInterface stp) {
SaTokenManager.stp = stp;
}
public synchronized static void initStp() {
if (stp == null) {
setStp(new StpInterfaceDefaultImpl());
}
}
}
package cn.dev33.satoken;
/**
* sa-token 工具类
*/
public class SaTokenUtil {
// sa-token 版本号
public static final String version = "v1.0.0";
// sa-token 开源地址
public static final String github_url = "https://github.com/click33/sa-token";
// 打印 sa-token
public static void printSaToken() {
String str =
"____ ____ ___ ____ _ _ ____ _ _ \r\n" +
"[__ |__| __ | | | |_/ |___ |\\ | \r\n" +
"___] | | | |__| | \\_ |___ | \\| \r\n" +
"sa-token:" + version + " \r\n" +
"GitHub:" + github_url + "\r\n";
System.out.println(str);
}
// 如果token为本次请求新创建的,则以此字符串为key存储在当前request中
public static final String just_created_save_key= "just_created_save_key_";
}
package cn.dev33.satoken.config;
/**
* sa-token 总配置类
*/
public class SaTokenConfig {
private String tokenName = "satoken"; // token名称(同时也是cookie名称)
private long timeout = 30 * 24 * 60 * 60; // token有效期,单位s 默认30天,-1为永不过期
private Boolean isShare = true; // 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录)
private Boolean isReadHead = false; // 是否在cookie读取不到token时,继续从请求header里继续尝试读取
private Boolean isReadBody = false; // 是否在header读取不到token时,继续从请求题参数里继续尝试读取
private Boolean isV = true; // 是否在初始化配置时打印版本字符画
public String getTokenName() {
return tokenName;
}
public void setTokenName(String tokenName) {
this.tokenName = tokenName;
}
public long getTimeout() {
return timeout;
}
public void setTimeout(long timeout) {
this.timeout = timeout;
}
public Boolean getIsShare() {
return isShare;
}
public void setIsShare(Boolean isShare) {
this.isShare = isShare;
}
public Boolean getIsReadHead() {
return isReadHead;
}
public void setIsReadHead(Boolean isReadHead) {
this.isReadHead = isReadHead;
}
public Boolean getIsReadBody() {
return isReadBody;
}
public void setIsReadBody(Boolean isReadBody) {
this.isReadBody = isReadBody;
}
public Boolean getIsV() {
return isV;
}
public void setIsV(Boolean isV) {
this.isV = isV;
}
@Override
public String toString() {
return "SaTokenConfig [tokenName=" + tokenName + ", timeout=" + timeout + ", isShare=" + isShare
+ ", isReadHead=" + isReadHead + ", isReadBody=" + isReadBody + ", isV=" + isV + "]";
}
}
package cn.dev33.satoken.config;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
创建一个配置文件
*/
public class SaTokenConfigFactory {
public static String configPath = "sa-token.properties"; // 默认配置文件地址
/**
* 根据指定路径获取配置信息
* @return 一个SaTokenConfig对象
*/
public static SaTokenConfig createConfig() {
Map<String, String> map = readPropToMap(configPath);
if(map == null){
// throw new RuntimeException("找不到配置文件:" + configPath, null);
}
return (SaTokenConfig)initPropByMap(map, new SaTokenConfig());
}
/**
* 将指定路径的properties配置文件读取到Map中
* @param propertiesPath 配置文件地址
* @return 一个Map
*/
private static Map<String, String> readPropToMap(String propertiesPath){
Map<String, String> map = new HashMap<String, String>();
try {
InputStream is = SaTokenConfigFactory.class.getClassLoader().getResourceAsStream(propertiesPath);
if(is == null){
return null;
}
Properties prop = new Properties();
prop.load(is);
for (String key : prop.stringPropertyNames()) {
map.put(key, prop.getProperty(key));
}
} catch (IOException e) {
throw new RuntimeException("配置文件(" + propertiesPath + ")加载失败", e);
}
return map;
}
/**
* 将 Map 的值映射到 Model 上
* @param map 属性集合
* @param obj 对象,或类型
* @return 返回实例化后的对象
*/
private static Object initPropByMap(Map<String, String> map, Object obj){
if(map == null){
map = new HashMap<>();
}
// 1、取出类型
Class<?> cs = null;
if(obj instanceof Class){ // 如果是一个类型,则将obj=null,以便完成静态属性反射赋值
cs = (Class<?>)obj;
obj = null;
}else{ // 如果是一个对象,则取出其类型
cs = obj.getClass();
}
// 2、遍历类型属性,反射赋值
for (Field field : cs.getDeclaredFields()) {
String value = map.get(field.getName());
if (value == null) {
continue; // 如果为空代表没有配置此项
}
try {
Object valueConvert = getObjectByClass(value, field.getType()); // 转换值类型
field.setAccessible(true);
field.set(obj, valueConvert);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException("属性赋值出错:" + field.getName(), e);
}
}
return obj;
}
/**
* 将字符串转化为指定数据类型
* @param str 值
* @param cs 要转换的类型
* @return
*/
@SuppressWarnings("unchecked")
private static <T>T getObjectByClass(String str, Class<T> cs){
Object value = null;
if(str == null){
value = null;
}else if (cs.equals(String.class)) {
value = str;
} else if (cs.equals(int.class)||cs.equals(Integer.class)) {
value = new Integer(str);
} else if (cs.equals(long.class)||cs.equals(Long.class)) {
value = new Long(str);
} else if (cs.equals(short.class)||cs.equals(Short.class)) {
value = new Short(str);
} else if (cs.equals(float.class)||cs.equals(Float.class)) {
value = new Float(str);
} else if (cs.equals(double.class)||cs.equals(Double.class)) {
value = new Double(str);
} else if (cs.equals(boolean.class)||cs.equals(Boolean.class)) {
value = new Boolean(str);
}else{
throw new RuntimeException("未能将值:" + str + ",转换类型为:" + cs, null);
}
return (T)value;
}
}
package cn.dev33.satoken.dao;
import cn.dev33.satoken.session.SaSession;
/**
* sa-token持久层的接口
*/
public interface SaTokenDao {
/**
* 根据key获取value ,如果没有,则返回空
* @param key 键名称
* @return
*/
public String getValue(String key);
/**
* 写入指定key-value键值对,并设定过期时间 (单位:秒)
* @param key 键名称
* @param value 值
* @param timeout 过期时间,单位:s
*/
public void setValue(String key, String value, long timeout);
/**
* 删除一个指定的key
* @param key
*/
public void delKey(String key);
/**
* 根据指定key的session,如果没有,则返回空
* @param key 键名称
* @return
*/
public SaSession getSaSession(String sessionId);
/**
* 将指定session持久化
* @param key 键名称
* @param value 值
* @param timeout 过期时间,单位: s
*/
public void saveSaSession(SaSession session, long timeout);
/**
* 更新指定session
*/
public void updateSaSession(SaSession session);
/**
* 删除一个指定的session
* @param key 键名称
*/
public void delSaSession(String sessionId);
}
package cn.dev33.satoken.dao;
import java.util.HashMap;
import java.util.Map;
import cn.dev33.satoken.session.SaSession;
/**
* sa-token持久层默认的实现类 , 基于内存Map
*/
public class SaTokenDaoDefault implements SaTokenDao {
/**
* 所有数据集合
*/
Map<String, Object> dataMap = new HashMap<String, Object>();
@Override
public String getValue(String key) {
return (String)dataMap.get(key);
}
@Override
public void setValue(String key, String value, long timeout) {
dataMap.put(key, value);
}
@Override
public void delKey(String key) {
dataMap.remove(key);
}
@Override
public SaSession getSaSession(String sessionId) {
return (SaSession)dataMap.get(sessionId);
}
@Override
public void saveSaSession(SaSession session, long timeout) {
dataMap.put(session.getId(), session);
}
@Override
public void updateSaSession(SaSession session) {
// 无动作
}
@Override
public void delSaSession(String sessionId) {
dataMap.remove(sessionId);
}
}
package cn.dev33.satoken.exception;
/**
* 没有登陆抛出的异常
*/
public class NotLoginException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 6806129545290130142L;
/**
* 创建一个
*/
public NotLoginException() {
super("当前账号未登录");
}
}
package cn.dev33.satoken.exception;
/**
* 没有指定权限码,抛出的异常
*/
public class NotPermissionException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 6806129545290130142L;
private Object code;
/**
* @return 获得权限码
*/
public Object getCode() {
return code;
}
public NotPermissionException(Object code) {
super("无此权限:" + code);
this.code = code;
}
// public NotPermissionException(Object code, String s) {
// super(s);
// this.code = code;
// }
}
package cn.dev33.satoken.session;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import cn.dev33.satoken.SaTokenManager;
/**
* session会话
* @author kong
*
*/
public class SaSession implements Serializable {
private static final long serialVersionUID = 1L;
private String id; // 会话id
private long createTime; // 当前会话创建时间
private Map<String, Object> dataMap; // 当前会话键值对
/**
* 构建一个 session对象
* @param id
*/
public SaSession(String id) {
this.id = id;
this.createTime = System.currentTimeMillis();
this.dataMap = new HashMap<String, Object>();
}
/**
* 获取会话id
* @return
*/
public String getId() {
return id;
}
/**
* 当前会话创建时间
*/
public long getCreateTime() {
return createTime;
}
/**
* 写入值
*/
public void setAttribute(String key, Object value) {
dataMap.put(key, value);
update();
}
/**
* 取值
*/
public Object getAttribute(String key) {
return dataMap.get(key);
}
/**
* 取值,并指定取不到值时的默认值
*/
public Object getAttribute(String key, Object default_value) {
Object value = getAttribute(key);
if(value != null) {
return value;
}
return default_value;
}
/**
* 移除一个key
*/
public void removeAttribute(String key) {
dataMap.remove(key);
update();
}
/**
* 清空所有key
*/
public void clearAttribute() {
dataMap.clear();
update();
}
/**
* 是否含有指定key
*/
public boolean containsAttribute(String key) {
return dataMap.keySet().contains(key);
}
/**
* 当前session会话所有key
*/
public Set<String> getAttributeKeys() {
return dataMap.keySet();
}
/**
* 获取数据集合(如果更新map里的值,请调用session.update()方法避免数据过时 )
*/
public Map<String, Object> getDataMap() {
return dataMap;
}
/**
* 将这个session从持久库更新一下
*/
public void update() {
SaTokenManager.getDao().updateSaSession(this);
}
// /** 注销会话(注销后,此session会话将不再存储服务器上) */
// public void logout() {
// SaTokenManager.getDao().delSaSession(this.id);
// }
}
package cn.dev33.satoken.session;
import cn.dev33.satoken.SaTokenManager;
/**
* sa-session工具类
* @author kong
*
*/
public class SaSessionUtil {
// 添加上指定前缀,防止恶意伪造session
public static String session_key = "custom";
public static String getSessionKey(String sessionId) {
return SaTokenManager.getConfig().getTokenName() + ":" + session_key + ":session:" + sessionId;
}
/** 指定key的session是否存在 */
public boolean isExists(String sessionId) {
return SaTokenManager.getDao().getSaSession(getSessionKey(sessionId)) != null;
}
/** 获取指定key的session, 如果没有,is_create=是否新建并返回 */
public static SaSession getSessionById(String sessionId, boolean is_create) {
SaSession session = SaTokenManager.getDao().getSaSession(getSessionKey(sessionId));
if(session == null && is_create) {
session = new SaSession(getSessionKey(sessionId));
SaTokenManager.getDao().saveSaSession(session, SaTokenManager.getConfig().getTimeout());
}
return session;
}
/** 获取指定key的session, 如果没有则新建并返回 */
public static SaSession getSessionById(String sessionId) {
return getSessionById(sessionId, true);
}
/** 删除指定key的session */
public static void delSessionById(String sessionId) {
SaTokenManager.getDao().delSaSession(getSessionKey(sessionId));
}
}
package cn.dev33.satoken.spring;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* 将此注解加到springboot启动类上,即可完成sa-token与springboot的集成
*/
@Documented
@Target({java.lang.annotation.ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Configuration
@Import({SpringSaToken.class})
public @interface SaTokenSetup {
}
package cn.dev33.satoken.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import cn.dev33.satoken.SaTokenManager;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.stp.StpInterface;
/**
* 与SpringBoot集成, 保证此类被扫描,即可完成sa-token与SpringBoot的集成
* @author kongyongshun
*
*/
@Component
public class SpringSaToken {
// 获取配置Bean
@Bean
@ConfigurationProperties(prefix="spring.sa-token")
public SaTokenConfig getSaTokenConfig() {
return new SaTokenConfig();
}
// 注入配置Bean
@Autowired
public void setConfig(SaTokenConfig saTokenConfig){
SaTokenManager.setConfig(saTokenConfig);
}
// 注入持久化Bean
@Autowired(required = false)
public void setDao(SaTokenDao dao){
SaTokenManager.setDao(dao);
}
// 注入权限认证Bean
@Autowired(required = false)
public void setStp(StpInterface stp){
SaTokenManager.setStp(stp);
}
}
package cn.dev33.satoken.stp;
import java.util.List;
/**
* 开放权限验证接口,方便重写
*/
public interface StpInterface {
/** 返回指定login_id所拥有的权限码集合 */
public List<Object> getPermissionCodeList(Object login_id, String login_key);
}
package cn.dev33.satoken.stp;
import java.util.ArrayList;
import java.util.List;
/**
* 权限验证接口 ,默认实现
*/
public class StpInterfaceDefaultImpl implements StpInterface {
@Override
public List<Object> getPermissionCodeList(Object login_id, String login_key) {
return new ArrayList<Object>();
}
}
package cn.dev33.satoken.stp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import cn.dev33.satoken.SaTokenManager;
import cn.dev33.satoken.SaTokenUtil;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.util.SaCookieUtil;
import cn.dev33.satoken.util.SpringMVCUtil;
/**
* sa-token 权限验证,逻辑 实现类
* <p>
* (stp = sa-token-permission 的缩写 )
*
*/
public class StpLogic {
private String login_key = ""; // 持久化的key前缀,多账号体系时以此值区分,比如:login、user、admin
public StpLogic(String login_key) {
this.login_key = login_key;
}
// =================== 获取token 相关 ===================
/** 随机生成一个tokenValue */
public String randomTokenValue() {
return UUID.randomUUID().toString();
}
/** 获取当前tokenValue */
public String getTokenValue(){
// 0、获取相应对象
HttpServletRequest request = SpringMVCUtil.getRequest();
SaTokenConfig config = SaTokenManager.getConfig();
String key_tokenName = getKey_tokenName();
// 1、尝试从request里读取
if(request.getAttribute(SaTokenUtil.just_created_save_key) != null) {
return String.valueOf(request.getAttribute(SaTokenUtil.just_created_save_key));
}
// 2、尝试从cookie里读取
Cookie cookie = SaCookieUtil.getCookie(request, key_tokenName);
if(cookie != null){
String tokenValue = cookie.getValue();
if(tokenValue != null) {
return tokenValue;
}
}
// 3、尝试从header力读取
if(config.getIsReadHead() == true){
String tokenValue = request.getHeader(key_tokenName);
if(tokenValue != null) {
return tokenValue;
}
}
// 4、尝试从请求体里面读取
if(config.getIsReadBody() == true){
String tokenValue = request.getParameter(key_tokenName);
if(tokenValue != null) {
return tokenValue;
}
}
// 5、都读取不到,那算了吧还是
return null;
}
/** 获取指定id的tokenValue */
public String getTokenValueByLoginId(Object login_id) {
return SaTokenManager.getDao().getValue(getKey_LoginId(login_id));
}
/** 获取当前会话的token信息:tokenName与tokenValue */
public Map<String, String> getTokenInfo() {
Map<String, String> map = new HashMap<String, String>();
map.put("tokenName", getKey_tokenName());
map.put("tokenValue", getTokenValue());
return map;
}
// =================== 登录相关操作 ===================
/** 在当前会话上登录id ,建议的类型:(long | int | String) */
public void setLoginId(Object login_id) {
// 1、获取相应对象
HttpServletRequest request = SpringMVCUtil.getRequest();
SaTokenConfig config = SaTokenManager.getConfig();
SaTokenDao dao = SaTokenManager.getDao();
// 2、获取tokenValue
String tokenValue = getTokenValueByLoginId(login_id); // 获取旧tokenValue
if(tokenValue == null){ // 为null则创建一个新的
tokenValue = randomTokenValue();
} else {
// 不为null, 并且配置不共享,则删掉原来,并且创建新的
if(config.getIsShare() == false){
dao.delKey(getKey_TokenValue(tokenValue));
tokenValue = randomTokenValue();
}
}
// 3、持久化
dao.setValue(getKey_TokenValue(tokenValue), String.valueOf(login_id), config.getTimeout()); // token -> uid
dao.setValue(getKey_LoginId(login_id), tokenValue, config.getTimeout()); // uid -> token
request.setAttribute(SaTokenUtil.just_created_save_key, tokenValue); // 保存到本次request里
SaCookieUtil.addCookie(SpringMVCUtil.getResponse(), getKey_tokenName(), tokenValue, "/", (int)config.getTimeout()); // cookie注入
}
/** 当前会话注销登录 */
public void logout() {
Object login_id = getLoginId_defaultNull();
if(login_id != null) {
logoutByLoginId(login_id);
SaCookieUtil.delCookie(SpringMVCUtil.getRequest(), SpringMVCUtil.getResponse(), getKey_tokenName()); // 清除cookie
}
}
/** 指定login_id的会话注销登录(踢人下线) */
public void logoutByLoginId(Object login_id) {
// 获取相应tokenValue
String tokenValue = getTokenValueByLoginId(login_id);
if(tokenValue == null) {
return;
}
// 清除相关数据
SaTokenManager.getDao().delKey(getKey_TokenValue(tokenValue)); // 清除token-id键值对
SaTokenManager.getDao().delKey(getKey_LoginId(login_id)); // 清除id-token键值对
SaTokenManager.getDao().delKey(getKey_session(login_id)); // 清除其session
// SaCookieUtil.delCookie(SpringMVCUtil.getRequest(), SpringMVCUtil.getResponse(), getKey_tokenName()); // 清除cookie
}
// 查询相关
/** 获取当前会话是否已经登录 */
public boolean isLogin() {
return getLoginId_defaultNull() != null;
}
/** 获取当前会话登录id, 如果未登录,则抛出异常 */
public Object getLoginId() {
Object login_id = getLoginId_defaultNull();
if(login_id == null) {
throw new NotLoginException();
}
return login_id;
}
/** 获取当前会话登录id, 如果未登录,则返回默认值 */
@SuppressWarnings("unchecked")
public <T>T getLoginId(T default_value) {
Object login_id = getLoginId_defaultNull();
if(login_id == null) {
return default_value;
}
return (T)login_id;
}
/** 获取当前会话登录id, 如果未登录,则返回null */
public Object getLoginId_defaultNull() {
String tokenValue = getTokenValue();
if(tokenValue != null) {
Object login_id = SaTokenManager.getDao().getValue(getKey_TokenValue(tokenValue));
if(login_id != null) {
return login_id;
}
}
return null;
}
/** 获取当前会话登录id, 并转换为String */
public String getLoginId_asString() {
return String.valueOf(getLoginId());
}
/** 获取当前会话登录id, 并转换为int */
public int getLoginId_asInt() {
// Object login_id = getLoginId();
// if(login_id instanceof Integer) {
// return (Integer)login_id;
// }
return Integer.valueOf(String.valueOf(getLoginId()));
}
/** 获取当前会话登录id, 并转换为long */
public long getLoginId_asLong() {
// Object login_id = getLoginId();
// if(login_id instanceof Long) {
// return (Long)login_id;
// }
return Long.valueOf(String.valueOf(getLoginId()));
}
// =================== session相关 ===================
/** 获取指定key的session, 如果没有,is_create=是否新建并返回 */
protected SaSession getSessionBySessionId(String sessionId, boolean is_create) {
SaSession session = SaTokenManager.getDao().getSaSession(sessionId);
if(session == null && is_create) {
session = new SaSession(sessionId);
SaTokenManager.getDao().saveSaSession(session, SaTokenManager.getConfig().getTimeout());
}
return session;
}
/** 获取指定login_id的session */
public SaSession getSessionByLoginId(Object login_id) {
return getSessionBySessionId(getKey_session(login_id), false);
}
/** 获取当前会话的session */
public SaSession getSession() {
return getSessionBySessionId(getKey_session(getLoginId()), true);
}
// =================== 权限验证操作 ===================
/** 指定login_id是否含有指定权限 */
public boolean hasPermission(Object login_id, Object pcode) {
List<Object> pcodeList = SaTokenManager.getStp().getPermissionCodeList(login_id, login_key);
return !(pcodeList == null || pcodeList.contains(pcode) == false);
}
/** 当前会话是否含有指定权限 */
public boolean hasPermission(Object pcode) {
return hasPermission(getLoginId(), pcode);
}
/** 当前账号是否含有指定权限 , 没有就抛出异常 */
public void checkPermission(Object pcode) {
if(hasPermission(pcode) == false) {
throw new NotPermissionException(pcode);
}
}
/** 当前账号是否含有指定权限 , 【指定多个,必须全都有】 */
public void checkPermissionAnd(Object... pcodeArray){
Object login_id = getLoginId();
List<Object> pcodeList = SaTokenManager.getStp().getPermissionCodeList(login_id, login_key);
for (Object pcode : pcodeArray) {
if(pcodeList.contains(pcode) == false) {
throw new NotPermissionException(pcode); // 没有权限抛出异常
}
}
}
/** 当前账号是否含有指定权限 , 【指定多个,有一个就可以了】 */
public void checkPermissionOr(Object... pcodeArray){
Object login_id = getLoginId();
List<Object> pcodeList = SaTokenManager.getStp().getPermissionCodeList(login_id, login_key);
for (Object pcode : pcodeArray) {
if(pcodeList.contains(pcode) == true) {
return; // 有的话提前退出
}
}
if(pcodeArray.length > 0) {
throw new NotPermissionException(pcodeArray[0]); // 没有权限抛出异常
}
}
// =================== 返回相应key ===================
/** 获取key:客户端 tokenName */
public String getKey_tokenName() {
return SaTokenManager.getConfig().getTokenName();
}
/** 获取key: tokenValue 持久化 */
public String getKey_TokenValue(String tokenValue) {
return SaTokenManager.getConfig().getTokenName() + ":" + login_key + ":token:" + tokenValue;
}
/** 获取key: id 持久化 */
public String getKey_LoginId(Object login_id) {
return SaTokenManager.getConfig().getTokenName() + ":" + login_key + ":id:" + login_id;
}
/** 获取key: session 持久化 */
public String getKey_session(Object login_id) {
return SaTokenManager.getConfig().getTokenName() + ":" + login_key + ":session:" + login_id;
}
}
package cn.dev33.satoken.stp;
import java.util.Map;
import org.springframework.stereotype.Service;
import cn.dev33.satoken.session.SaSession;
/**
* 一个默认的实现
*/
@Service
public class StpUtil {
// 底层的 StpLogic 对象
public static StpLogic stpLogic = new StpLogic("login");
// =================== 获取token 相关 ===================
/** 获取当前tokenValue */
public static String getTokenValue() {
return stpLogic.getTokenValue();
}
/** 获取指定id的tokenValue */
public static String getTokenValueByLoginId(Object login_id) {
return stpLogic.getTokenValueByLoginId(login_id);
}
/** 获取当前会话的token信息:tokenName与tokenValue */
public static Map<String, String> getTokenInfo() {
return stpLogic.getTokenInfo();
}
// =================== 登录相关操作 ===================
/** 在当前会话上设置登录id,建议的类型:(long | int | String) */
public static void setLoginId(Object login_id) {
stpLogic.setLoginId(login_id);
}
/** 当前会话注销登录 */
public static void logout() {
stpLogic.logout();
}
/** 指定login_id的会话注销登录(踢人下线) */
public static void logoutByLoginId(Object login_id) {
stpLogic.logoutByLoginId(login_id);
}
// 查询相关
/** 获取当前会话是否已经登录 */
public static boolean isLogin() {
return stpLogic.isLogin();
}
/** 获取当前会话登录id, 如果未登录,则抛出异常 */
public static Object getLoginId() {
return stpLogic.getLoginId();
}
/** 获取当前会话登录id, 如果未登录,则返回默认值 */
public static <T> T getLoginId(T default_value) {
return stpLogic.getLoginId(default_value);
}
/** 获取当前会话登录id, 如果未登录,则返回null */
public static Object getLoginId_defaultNull() {
return stpLogic.getLoginId_defaultNull();
}
/** 获取当前会话登录id, 并转换为String */
public static String getLoginId_asString() {
return stpLogic.getLoginId_asString();
}
/** 获取当前会话登录id, 并转换为int */
public static int getLoginId_asInt() {
return stpLogic.getLoginId_asInt();
}
/** 获取当前会话登录id, 并转换为long */
public static long getLoginId_asLong() {
return stpLogic.getLoginId_asLong();
}
// =================== session相关 ===================
/** 获取指定login_id的session */
public static SaSession getSessionByLoginId(Object login_id) {
return stpLogic.getSessionByLoginId(login_id);
}
/** 获取当前会话的session */
public static SaSession getSession() {
return stpLogic.getSession();
}
// =================== 权限验证操作 ===================
/** 指定login_id是否含有指定权限 */
public static boolean hasPermission(Object login_id, Object pcode) {
return stpLogic.hasPermission(login_id, pcode);
}
/** 当前会话是否含有指定权限 */
public static boolean hasPermission(Object pcode) {
return stpLogic.hasPermission(pcode);
}
/** 当前账号是否含有指定权限 , 没有就抛出异常 */
public static void checkPermission(Object pcode) {
stpLogic.checkPermission(pcode);
}
/** 当前账号是否含有指定权限 , 【指定多个,必须全都有】 */
public static void checkPermissionAnd(Object... pcodeArray) {
stpLogic.checkPermissionAnd(pcodeArray);
}
/** 当前账号是否含有指定权限 , 【指定多个,有一个就可以了】 */
public static void checkPermissionOr(Object... pcodeArray) {
stpLogic.checkPermissionOr(pcodeArray);
}
}
package cn.dev33.satoken.util;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* cookie工具类
* @author kong
*
*/
public class SaCookieUtil {
/**
* 获取指定cookie
*/
public static Cookie getCookie(HttpServletRequest request, String cookieName) {
Cookie[] cookies = request.getCookies();
if(cookies != null) {
for(int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
if(cookie != null && cookieName.equals(cookie.getName())) {
return cookie;
}
}
}
return null;
}
/**
* 添加cookie
*/
public static void addCookie(HttpServletResponse response,String name,String value,String path,int timeout) {
Cookie cookie = new Cookie(name, value);
if(path == null) {
path = "/";
}
cookie.setPath(path);
cookie.setMaxAge(timeout);
response.addCookie(cookie);
}
/**
* 删除cookie
*/
public static void delCookie(HttpServletRequest request,HttpServletResponse response,String name) {
Cookie[] cookies = request.getCookies();
if(cookies != null){
for(Cookie cookie : cookies) {
if(cookies != null && (name).equals(cookie.getName())) {
addCookie(response,name,null,null,0);
return;
}
}
}
}
/**
* 修改cookie的value值
*/
public static void updateCookie(HttpServletRequest request,HttpServletResponse response,String name,String value) {
Cookie[] cookies = request.getCookies();
if(cookies != null){
for(Cookie cookie : cookies) {
if(cookies != null && (name).equals(cookie.getName())) {
addCookie(response,name,value,cookie.getPath(),cookie.getMaxAge());
return;
}
}
}
}
}
\ No newline at end of file
package cn.dev33.satoken.util;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* SpringMVC相关操作
* @author kong
*
*/
public class SpringMVCUtil {
// 获取当前会话的 request
public static HttpServletRequest getRequest() {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();// 大善人SpringMVC提供的封装
if(servletRequestAttributes == null) {
throw new RuntimeException("当前环境非JavaWeb");
}
return servletRequestAttributes.getRequest();
}
// 获取当前会话的
public static HttpServletResponse getResponse() {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();// 大善人SpringMVC提供的封装
if(servletRequestAttributes == null) {
throw new RuntimeException("当前环境非JavaWeb");
}
return servletRequestAttributes.getResponse();
}
}
package com.pj;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import cn.dev33.satoken.SaTokenManager;
import cn.dev33.satoken.spring.SaTokenSetup;
@SaTokenSetup // 标注启动 sa-token
@SpringBootApplication
public class SaTokenApplication {
public static void main(String[] args) {
SpringApplication.run(SaTokenApplication.class, args); // run-->
System.out.println(SaTokenManager.getConfig());
}
}
\ No newline at end of file
# 端口
server:
port: 8081
spring:
# sa-token配置
sa-token:
# token名称(同时也是cookie名称)
token-name: satoken
# token有效期,单位s 默认30天,-1为永不过期
timeout: 2592000
# 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录)
is-share: true
# 是否在cookie读取不到token时,继续从请求header里继续尝试读取
is-read-head: true
# 是否在header读取不到token时,继续从请求题参数里继续尝试读取
is-read-body: true
# 是否在初始化配置时打印版本字符画
is-v: true
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>sa-token在线文档</title>
</head>
<body>
<h1>sa-token在线文档</h1>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册