mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-09-20 18:47:58 +08:00
细化未登录异常类型、Cookie操作改为接口代理模式等功能点,为 v1.5.0 版本做准备
This commit is contained in:
@@ -26,18 +26,18 @@
|
||||
</dependency>
|
||||
|
||||
<!-- 开发测试 -->
|
||||
<!-- <dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-dev</artifactId>
|
||||
<version>1.4.0</version>
|
||||
</dependency> -->
|
||||
</dependency>
|
||||
|
||||
<!-- sa-token 权限认证, 在线文档:http://sa-token.dev33.cn/ -->
|
||||
<dependency>
|
||||
<!-- <dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token</artifactId>
|
||||
<version>1.4.0</version>
|
||||
</dependency>
|
||||
</dependency> -->
|
||||
|
||||
<!-- SpringBoot整合redis -->
|
||||
<dependency>
|
||||
|
@@ -13,6 +13,7 @@ public class SaTokenDemoApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SaTokenDemoApplication.class, args);
|
||||
System.out.println("启动成功:sa-token配置如下:" + SaTokenManager.getConfig());
|
||||
// StpUtil.getSessionByLoginId(10001)
|
||||
}
|
||||
|
||||
|
||||
|
@@ -15,7 +15,7 @@ import cn.dev33.satoken.config.SaTokenConfig;
|
||||
@Configuration
|
||||
public class MySaTokenConfig implements WebMvcConfigurer {
|
||||
|
||||
// 获取配置Bean (以代码的方式配置sa-token)
|
||||
// 获取配置Bean (以代码的方式配置sa-token, 此配置会覆盖yml中的配置 )
|
||||
@Primary
|
||||
@Bean(name="MySaTokenConfig")
|
||||
public SaTokenConfig getSaTokenConfig() {
|
||||
|
@@ -7,7 +7,7 @@ import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
// import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import cn.dev33.satoken.dao.SaTokenDao;
|
||||
import cn.dev33.satoken.session.SaSession;
|
||||
@@ -15,7 +15,7 @@ import cn.dev33.satoken.session.SaSession;
|
||||
/**
|
||||
* sa-token持久层的实现类 , 基于redis
|
||||
*/
|
||||
// @Component // 打开此注解,保证此类被springboot扫描,即可完成sa-token与redis的集成
|
||||
@Component // 打开此注解,保证此类被springboot扫描,即可完成sa-token与redis的集成
|
||||
public class SaTokenDaoRedis implements SaTokenDao {
|
||||
|
||||
|
||||
@@ -46,6 +46,16 @@ public class SaTokenDaoRedis implements SaTokenDao {
|
||||
stringRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
// 更新指定key-value键值对 (过期时间取原来的值)
|
||||
@Override
|
||||
public void updateValue(String key, String value) {
|
||||
long expire = redisTemplate.getExpire(key);
|
||||
if(expire == -2) { // -2 = 无此键
|
||||
return;
|
||||
}
|
||||
stringRedisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
// 删除一个指定的key
|
||||
@Override
|
||||
public void delKey(String key) {
|
||||
@@ -77,7 +87,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
|
||||
|
||||
// 删除一个指定的session
|
||||
@Override
|
||||
public void delSaSession(String sessionId) {
|
||||
public void deleteSaSession(String sessionId) {
|
||||
redisTemplate.delete(sessionId);
|
||||
}
|
||||
|
||||
@@ -88,4 +98,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,238 @@
|
||||
package com.pj.satoken;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import cn.dev33.satoken.SaTokenManager;
|
||||
import cn.dev33.satoken.session.SaSession;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
|
||||
/**
|
||||
* 一个默认的实现
|
||||
* @author kong
|
||||
*/
|
||||
@Service
|
||||
public class StpUserUtil {
|
||||
|
||||
/**
|
||||
* 底层的 StpLogic 对象
|
||||
*/
|
||||
public static StpLogic stpLogic = new StpLogic("user") {
|
||||
@Override
|
||||
public String getKeyTokenName() {
|
||||
return SaTokenManager.getConfig().getTokenName() + "-user";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// =================== 获取token 相关 ===================
|
||||
|
||||
/**
|
||||
* 返回token名称
|
||||
* @return 此StpLogic的token名称
|
||||
*/
|
||||
public static String getTokenName() {
|
||||
return stpLogic.getTokenName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前tokenValue
|
||||
* @return 当前tokenValue
|
||||
*/
|
||||
public static String getTokenValue() {
|
||||
return stpLogic.getTokenValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定id的tokenValue
|
||||
* @param loginId .
|
||||
* @return
|
||||
*/
|
||||
public static String getTokenValueByLoginId(Object loginId) {
|
||||
return stpLogic.getTokenValueByLoginId(loginId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话的token信息:tokenName与tokenValue
|
||||
* @return 一个Map对象
|
||||
*/
|
||||
public static Map<String, String> getTokenInfo() {
|
||||
return stpLogic.getTokenInfo();
|
||||
}
|
||||
|
||||
// =================== 登录相关操作 ===================
|
||||
|
||||
/**
|
||||
* 在当前会话上登录id
|
||||
* @param loginId 登录id ,建议的类型:(long | int | String)
|
||||
*/
|
||||
public static void setLoginId(Object loginId) {
|
||||
stpLogic.setLoginId(loginId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前会话注销登录
|
||||
*/
|
||||
public static void logout() {
|
||||
stpLogic.logout();
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定loginId的会话注销登录(踢人下线)
|
||||
* @param loginId 账号id
|
||||
*/
|
||||
public static void logoutByLoginId(Object loginId) {
|
||||
stpLogic.logoutByLoginId(loginId);
|
||||
}
|
||||
|
||||
// 查询相关
|
||||
|
||||
/**
|
||||
* 获取当前会话是否已经登录
|
||||
* @return 是否已登录
|
||||
*/
|
||||
public static boolean isLogin() {
|
||||
return stpLogic.isLogin();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检验当前会话是否已经登录,如未登录,则抛出异常
|
||||
*/
|
||||
public static void checkLogin() {
|
||||
getLoginId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话登录id, 如果未登录,则抛出异常
|
||||
* @return .
|
||||
*/
|
||||
public static Object getLoginId() {
|
||||
return stpLogic.getLoginId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话登录id, 如果未登录,则返回默认值
|
||||
* @param defaultValue .
|
||||
* @return .
|
||||
*/
|
||||
public static <T> T getLoginId(T defaultValue) {
|
||||
return stpLogic.getLoginId(defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话登录id, 如果未登录,则返回null
|
||||
* @return
|
||||
*/
|
||||
public static Object getLoginIdDefaultNull() {
|
||||
return stpLogic.getLoginIdDefaultNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话登录id, 并转换为String
|
||||
* @return
|
||||
*/
|
||||
public static String getLoginIdAsString() {
|
||||
return stpLogic.getLoginIdAsString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话登录id, 并转换为int
|
||||
* @return
|
||||
*/
|
||||
public static int getLoginIdAsInt() {
|
||||
return stpLogic.getLoginIdAsInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话登录id, 并转换为long
|
||||
* @return
|
||||
*/
|
||||
public static long getLoginIdAsLong() {
|
||||
return stpLogic.getLoginIdAsLong();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定token对应的登录id,如果未登录,则返回 null
|
||||
* @return .
|
||||
*/
|
||||
public static Object getLoginIdByToken(String tokenValue) {
|
||||
return stpLogic.getLoginIdByToken(tokenValue);
|
||||
}
|
||||
|
||||
// =================== session相关 ===================
|
||||
|
||||
/**
|
||||
* 获取指定loginId的session, 如果没有,isCreate=是否新建并返回
|
||||
* @param loginId 登录id
|
||||
* @param isCreate 是否新建
|
||||
* @return SaSession
|
||||
*/
|
||||
public static SaSession getSessionByLoginId(Object loginId, boolean isCreate) {
|
||||
return stpLogic.getSessionByLoginId(loginId, isCreate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定loginId的session
|
||||
* @param loginId .
|
||||
* @return .
|
||||
*/
|
||||
public static SaSession getSessionByLoginId(Object loginId) {
|
||||
return stpLogic.getSessionByLoginId(loginId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话的session
|
||||
* @return
|
||||
*/
|
||||
public static SaSession getSession() {
|
||||
return stpLogic.getSession();
|
||||
}
|
||||
|
||||
// =================== 权限验证操作 ===================
|
||||
|
||||
/**
|
||||
* 指定loginId是否含有指定权限
|
||||
* @param loginId .
|
||||
* @param pcode .
|
||||
* @return .
|
||||
*/
|
||||
public static boolean hasPermission(Object loginId, Object pcode) {
|
||||
return stpLogic.hasPermission(loginId, pcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前会话是否含有指定权限
|
||||
* @param pcode .
|
||||
* @return .
|
||||
*/
|
||||
public static boolean hasPermission(Object pcode) {
|
||||
return stpLogic.hasPermission(pcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前账号是否含有指定权限 , 没有就抛出异常
|
||||
* @param pcode .
|
||||
*/
|
||||
public static void checkPermission(Object pcode) {
|
||||
stpLogic.checkPermission(pcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前账号是否含有指定权限 , 【指定多个,必须全都有】
|
||||
* @param pcodeArray .
|
||||
*/
|
||||
public static void checkPermissionAnd(Object... pcodeArray) {
|
||||
stpLogic.checkPermissionAnd(pcodeArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前账号是否含有指定权限 , 【指定多个,有一个就可以了】
|
||||
* @param pcodeArray .
|
||||
*/
|
||||
public static void checkPermissionOr(Object... pcodeArray) {
|
||||
stpLogic.checkPermissionOr(pcodeArray);
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -36,6 +36,20 @@ public class GlobalException {
|
||||
AjaxJson aj = null;
|
||||
if (e instanceof NotLoginException) { // 如果是未登录异常
|
||||
aj = AjaxJson.getNotLogin();
|
||||
// 判断具体是什么类型
|
||||
NotLoginException ee = (NotLoginException) e;
|
||||
if(ee.getType() == NotLoginException.NOT_TOKEN) {
|
||||
aj.setMsg("未提供token");
|
||||
}
|
||||
if(ee.getType() == NotLoginException.INVALID_TOKEN) {
|
||||
aj.setMsg("token无效");
|
||||
}
|
||||
if(ee.getType() == NotLoginException.BE_REPLACED) {
|
||||
aj.setMsg("token已被顶下线");
|
||||
}
|
||||
if(ee.getType() == NotLoginException.TOKEN_TIMEOUT) {
|
||||
aj.setMsg("token已过期");
|
||||
}
|
||||
} else if(e instanceof NotPermissionException) { // 如果是权限异常
|
||||
NotPermissionException ee = (NotPermissionException) e;
|
||||
aj = AjaxJson.getNotJur("无此权限:" + ee.getCode());
|
||||
|
@@ -112,10 +112,29 @@ public class TestController {
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
// 测试注解式鉴权, 浏览器访问: http://localhost:8081/test/getInfo
|
||||
@SaCheckLogin // 注解式鉴权:当前会话必须登录才能通过
|
||||
@RequestMapping("getInfo")
|
||||
public AjaxJson getInfo() {
|
||||
return AjaxJson.getSuccessData("用户信息");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 测试 浏览器访问: http://localhost:8081/test/test
|
||||
@RequestMapping("test")
|
||||
public AjaxJson test() {
|
||||
StpUtil.setLoginId(10001);
|
||||
|
||||
// System.out.println(StpUtil.getSession().getId());
|
||||
// System.out.println(StpUserUtil.getSession().getId());
|
||||
StpUtil.getSessionByLoginId(10001).setAttribute("name", "123");
|
||||
System.out.println(StpUtil.getSessionByLoginId(10001).getAttribute("name"));
|
||||
|
||||
return AjaxJson.getSuccess();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@@ -1,9 +1,13 @@
|
||||
package cn.dev33.satoken;
|
||||
|
||||
import cn.dev33.satoken.action.SaTokenAction;
|
||||
import cn.dev33.satoken.action.SaTokenActionDefaultImpl;
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import cn.dev33.satoken.config.SaTokenConfigFactory;
|
||||
import cn.dev33.satoken.cookie.SaCookieOper;
|
||||
import cn.dev33.satoken.cookie.SaCookieOperDefaultImpl;
|
||||
import cn.dev33.satoken.dao.SaTokenDao;
|
||||
import cn.dev33.satoken.dao.SaTokenDaoDefault;
|
||||
import cn.dev33.satoken.dao.SaTokenDaoDefaultImpl;
|
||||
import cn.dev33.satoken.stp.StpInterface;
|
||||
import cn.dev33.satoken.stp.StpInterfaceDefaultImpl;
|
||||
import cn.dev33.satoken.util.SaTokenInsideUtil;
|
||||
@@ -38,7 +42,6 @@ public class SaTokenManager {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 持久化 Bean
|
||||
*/
|
||||
@@ -54,11 +57,10 @@ public class SaTokenManager {
|
||||
}
|
||||
public synchronized static void initDao() {
|
||||
if (dao == null) {
|
||||
setDao(new SaTokenDaoDefault());
|
||||
setDao(new SaTokenDaoDefaultImpl());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 权限认证 Bean
|
||||
*/
|
||||
@@ -78,6 +80,45 @@ public class SaTokenManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sa-token行为 Bean
|
||||
*/
|
||||
public static SaTokenAction sta;
|
||||
public static SaTokenAction getSta() {
|
||||
if (sta == null) {
|
||||
initSta();
|
||||
}
|
||||
return sta;
|
||||
}
|
||||
public static void setSta(SaTokenAction sta) {
|
||||
SaTokenManager.sta = sta;
|
||||
}
|
||||
public synchronized static void initSta() {
|
||||
if (sta == null) {
|
||||
setSta(new SaTokenActionDefaultImpl());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sa-token cookie操作 Bean
|
||||
*/
|
||||
public static SaCookieOper saCookieOper;
|
||||
public static SaCookieOper getSaCookieOper() {
|
||||
if (saCookieOper == null) {
|
||||
initgetSaCookieOper();
|
||||
}
|
||||
return saCookieOper;
|
||||
}
|
||||
public static void setSaCookieOper(SaCookieOper saCookieOper) {
|
||||
SaTokenManager.saCookieOper = saCookieOper;
|
||||
}
|
||||
public synchronized static void initgetSaCookieOper() {
|
||||
if (saCookieOper == null) {
|
||||
setSaCookieOper(new SaCookieOperDefaultImpl());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -0,0 +1,30 @@
|
||||
package cn.dev33.satoken.action;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public interface SaTokenAction {
|
||||
|
||||
|
||||
/**
|
||||
* 获取当前请求的Request对象
|
||||
* @return 当前请求的Request对象
|
||||
*/
|
||||
public HttpServletRequest getCurrRequest();
|
||||
|
||||
/**
|
||||
* 获取当前会话的 response
|
||||
* @return
|
||||
*/
|
||||
public HttpServletResponse getResponse();
|
||||
|
||||
/**
|
||||
* 生成一个token
|
||||
* @param loginId 账号id
|
||||
* @param loginKey 登录标识key
|
||||
* @return
|
||||
*/
|
||||
public String createToken(Object loginId, String loginKey);
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
package cn.dev33.satoken.action;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import cn.dev33.satoken.util.SpringMvcUtil;
|
||||
|
||||
/**
|
||||
* 对 SaTokenAction 接口的默认实现
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaTokenActionDefaultImpl implements SaTokenAction {
|
||||
|
||||
/**
|
||||
* 获取当前请求的Request对象
|
||||
*/
|
||||
@Override
|
||||
public HttpServletRequest getCurrRequest() {
|
||||
return SpringMvcUtil.getRequest();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取当前请求的Response对象
|
||||
*/
|
||||
@Override
|
||||
public HttpServletResponse getResponse() {
|
||||
return SpringMvcUtil.getResponse();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成一个token
|
||||
*/
|
||||
@Override
|
||||
public String createToken(Object loginId, String loginKey) {
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
package cn.dev33.satoken.cookie;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* sa-token 对cookie的相关操作 接口类
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public interface SaCookieOper {
|
||||
|
||||
/**
|
||||
* 获取指定cookie .
|
||||
*
|
||||
* @param request .
|
||||
* @param cookieName .
|
||||
* @return .
|
||||
*/
|
||||
public Cookie getCookie(HttpServletRequest request, String cookieName);
|
||||
|
||||
/**
|
||||
* 添加cookie
|
||||
*
|
||||
* @param response .
|
||||
* @param name .
|
||||
* @param value .
|
||||
* @param path .
|
||||
* @param timeout .
|
||||
*/
|
||||
public void addCookie(HttpServletResponse response, String name, String value, String path, int timeout);
|
||||
|
||||
/**
|
||||
* 删除cookie .
|
||||
*
|
||||
* @param request .
|
||||
* @param response .
|
||||
* @param name .
|
||||
*/
|
||||
public void delCookie(HttpServletRequest request, HttpServletResponse response, String name);
|
||||
|
||||
/**
|
||||
* 修改cookie的value值
|
||||
*
|
||||
* @param request .
|
||||
* @param response .
|
||||
* @param name .
|
||||
* @param value .
|
||||
*/
|
||||
public void updateCookie(HttpServletRequest request, HttpServletResponse response, String name, String value);
|
||||
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
package cn.dev33.satoken.cookie;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import cn.dev33.satoken.util.SaCookieUtil;
|
||||
|
||||
/**
|
||||
* sa-token 对cookie的相关操作 接口实现类
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaCookieOperDefaultImpl implements SaCookieOper {
|
||||
|
||||
/**
|
||||
* 获取指定cookie
|
||||
*/
|
||||
public Cookie getCookie(HttpServletRequest request, String cookieName) {
|
||||
return SaCookieUtil.getCookie(request, cookieName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加cookie
|
||||
*/
|
||||
public void addCookie(HttpServletResponse response, String name, String value, String path, int timeout) {
|
||||
SaCookieUtil.addCookie(response, name, value, path, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除cookie
|
||||
*/
|
||||
public void delCookie(HttpServletRequest request, HttpServletResponse response, String name) {
|
||||
SaCookieUtil.delCookie(request, response, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改cookie的value值
|
||||
*/
|
||||
public void updateCookie(HttpServletRequest request, HttpServletResponse response, String name, String value) {
|
||||
SaCookieUtil.updateCookie(request, response, name, value);
|
||||
}
|
||||
|
||||
}
|
@@ -25,6 +25,13 @@ public interface SaTokenDao {
|
||||
*/
|
||||
public void setValue(String key, String value, long timeout);
|
||||
|
||||
/**
|
||||
* 修改指定key-value键值对 (过期时间取原来的值)
|
||||
* @param key 键名称
|
||||
* @param value 值
|
||||
*/
|
||||
public void updateValue(String key, String value);
|
||||
|
||||
/**
|
||||
* 删除一个指定的key
|
||||
* @param key 键名称
|
||||
@@ -57,7 +64,7 @@ public interface SaTokenDao {
|
||||
* 删除一个指定的session
|
||||
* @param sessionId sessionId
|
||||
*/
|
||||
public void delSaSession(String sessionId);
|
||||
public void deleteSaSession(String sessionId);
|
||||
|
||||
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@ import cn.dev33.satoken.session.SaSession;
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaTokenDaoDefault implements SaTokenDao {
|
||||
public class SaTokenDaoDefaultImpl implements SaTokenDao {
|
||||
|
||||
/**
|
||||
* 所有数据集合
|
||||
@@ -28,6 +28,11 @@ public class SaTokenDaoDefault implements SaTokenDao {
|
||||
dataMap.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateValue(String key, String value) {
|
||||
this.setValue(key, value, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delKey(String key) {
|
||||
dataMap.remove(key);
|
||||
@@ -50,7 +55,7 @@ public class SaTokenDaoDefault implements SaTokenDao {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delSaSession(String sessionId) {
|
||||
public void deleteSaSession(String sessionId) {
|
||||
dataMap.remove(sessionId);
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package cn.dev33.satoken.exception;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 没有登陆抛出的异常
|
||||
@@ -15,12 +16,50 @@ public class NotLoginException extends RuntimeException {
|
||||
private static final long serialVersionUID = 6806129545290130142L;
|
||||
|
||||
|
||||
// ------------------- 异常类型常量 --------------------
|
||||
|
||||
/*
|
||||
* 这里简述一下为什么要把常量设计为String类型
|
||||
* 因为loginId刚取出的时候类型为String,为了避免两者相比较时不必要的类型转换带来的性能消耗,故在此直接将常量类型设计为String
|
||||
*/
|
||||
|
||||
/** 表示未提供token */
|
||||
public static final String NOT_TOKEN = "-1";
|
||||
|
||||
/** 表示token无效 */
|
||||
public static final String INVALID_TOKEN = "-2";
|
||||
|
||||
/** 表示token已被顶下线 */
|
||||
public static final String BE_REPLACED = "-3";
|
||||
|
||||
/** 表示token已过期 */
|
||||
public static final String TOKEN_TIMEOUT = "-4";
|
||||
|
||||
/**
|
||||
* login_key
|
||||
* 代表异常token的标志集合
|
||||
*/
|
||||
public static final List<String> ABNORMAL_LIST = Arrays.asList(NOT_TOKEN, INVALID_TOKEN, BE_REPLACED, TOKEN_TIMEOUT);
|
||||
|
||||
|
||||
/**
|
||||
* 异常类型
|
||||
*/
|
||||
private String type;
|
||||
/**
|
||||
* 获取异常类型
|
||||
* @return
|
||||
*/
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* loginKey
|
||||
*/
|
||||
private String loginKey;
|
||||
/**
|
||||
* 获得login_key
|
||||
* 获得loginKey
|
||||
* @return login_key
|
||||
*/
|
||||
public String getLoginKey() {
|
||||
@@ -28,21 +67,24 @@ public class NotLoginException extends RuntimeException {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建一个
|
||||
*/
|
||||
public NotLoginException() {
|
||||
this(StpUtil.stpLogic.loginKey);
|
||||
}
|
||||
|
||||
|
||||
// /**
|
||||
// * 创建一个
|
||||
// */
|
||||
// public NotLoginException() {
|
||||
// this(StpUtil.stpLogic.loginKey);
|
||||
// }
|
||||
|
||||
/**
|
||||
* 创建一个
|
||||
* @param loginKey login_key
|
||||
*/
|
||||
public NotLoginException(String loginKey) {
|
||||
public NotLoginException(String loginKey, String type) {
|
||||
// 这里到底要不要拼接上login_key呢?纠结
|
||||
super("当前会话未登录");
|
||||
this.loginKey = loginKey;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -53,8 +53,8 @@ public class SaSessionCustomUtil {
|
||||
* 删除指定key的session
|
||||
* @param sessionId 删除指定key
|
||||
*/
|
||||
public static void delSessionById(String sessionId) {
|
||||
SaTokenManager.getDao().delSaSession(getSessionKey(sessionId));
|
||||
public static void deleteSessionById(String sessionId) {
|
||||
SaTokenManager.getDao().deleteSaSession(getSessionKey(sessionId));
|
||||
}
|
||||
|
||||
|
||||
|
@@ -3,7 +3,6 @@ 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;
|
||||
@@ -14,9 +13,7 @@ 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.SaTokenInsideUtil;
|
||||
import cn.dev33.satoken.util.SpringMvcUtil;
|
||||
|
||||
/**
|
||||
* sa-token 权限验证,逻辑 实现类
|
||||
@@ -42,13 +39,20 @@ public class StpLogic {
|
||||
|
||||
// =================== 获取token 相关 ===================
|
||||
|
||||
/**
|
||||
* 返回token名称
|
||||
* @return 此StpLogic的token名称
|
||||
*/
|
||||
public String getTokenName() {
|
||||
return getKeyTokenName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机生成一个tokenValue
|
||||
* @return 生成的tokenValue
|
||||
*/
|
||||
public String randomTokenValue() {
|
||||
return UUID.randomUUID().toString();
|
||||
public String randomTokenValue(Object loginId) {
|
||||
return SaTokenManager.getSta().createToken(loginId, loginKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,9 +61,9 @@ public class StpLogic {
|
||||
*/
|
||||
public String getTokenValue(){
|
||||
// 0、获取相应对象
|
||||
HttpServletRequest request = SpringMvcUtil.getRequest();
|
||||
HttpServletRequest request = SaTokenManager.getSta().getCurrRequest();
|
||||
SaTokenConfig config = SaTokenManager.getConfig();
|
||||
String keyTokenName = getKeyTokenName();
|
||||
String keyTokenName = getTokenName();
|
||||
|
||||
// 1、尝试从request里读取
|
||||
if(request.getAttribute(SaTokenInsideUtil.JUST_CREATED_SAVE_KEY) != null) {
|
||||
@@ -81,7 +85,7 @@ public class StpLogic {
|
||||
}
|
||||
// 4、尝试从cookie里读取
|
||||
if(config.getIsReadCookie() == true){
|
||||
Cookie cookie = SaCookieUtil.getCookie(request, keyTokenName);
|
||||
Cookie cookie = SaTokenManager.getSaCookieOper().getCookie(request, keyTokenName);
|
||||
if(cookie != null){
|
||||
String tokenValue = cookie.getValue();
|
||||
if(tokenValue != null) {
|
||||
@@ -108,7 +112,7 @@ public class StpLogic {
|
||||
*/
|
||||
public Map<String, String> getTokenInfo() {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("tokenName", getKeyTokenName());
|
||||
map.put("tokenName", getTokenName());
|
||||
map.put("tokenValue", getTokenValue());
|
||||
return map;
|
||||
}
|
||||
@@ -123,19 +127,20 @@ public class StpLogic {
|
||||
public void setLoginId(Object loginId) {
|
||||
|
||||
// 1、获取相应对象
|
||||
HttpServletRequest request = SpringMvcUtil.getRequest();
|
||||
HttpServletRequest request = SaTokenManager.getSta().getCurrRequest();
|
||||
SaTokenConfig config = SaTokenManager.getConfig();
|
||||
SaTokenDao dao = SaTokenManager.getDao();
|
||||
|
||||
// 2、获取tokenValue
|
||||
String tokenValue = getTokenValueByLoginId(loginId); // 获取旧tokenValue
|
||||
if(tokenValue == null){ // 为null则创建一个新的
|
||||
tokenValue = randomTokenValue();
|
||||
tokenValue = randomTokenValue(loginId);
|
||||
} else {
|
||||
// 不为null, 并且配置不共享,则删掉原来,并且创建新的
|
||||
// 不为null, 并且配置不共享,则:将原来的标记为[被顶替]
|
||||
if(config.getIsShare() == false){
|
||||
dao.delKey(getKeyTokenValue(tokenValue));
|
||||
tokenValue = randomTokenValue();
|
||||
// dao.delKey(getKeyTokenValue(tokenValue));
|
||||
dao.updateValue(getKeyTokenValue(tokenValue), NotLoginException.BE_REPLACED);
|
||||
tokenValue = randomTokenValue(loginId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +149,7 @@ public class StpLogic {
|
||||
dao.setValue(getKeyLoginId(loginId), tokenValue, config.getTimeout()); // uid -> token
|
||||
request.setAttribute(SaTokenInsideUtil.JUST_CREATED_SAVE_KEY, tokenValue); // 保存到本次request里
|
||||
if(config.getIsReadCookie() == true){
|
||||
SaCookieUtil.addCookie(SpringMvcUtil.getResponse(), getKeyTokenName(), tokenValue, "/", (int)config.getTimeout()); // cookie注入
|
||||
SaTokenManager.getSaCookieOper().addCookie(SaTokenManager.getSta().getResponse(), getTokenName(), tokenValue, "/", (int)config.getTimeout()); // cookie注入
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,14 +157,27 @@ public class StpLogic {
|
||||
* 当前会话注销登录
|
||||
*/
|
||||
public void logout() {
|
||||
Object loginId = getLoginIdDefaultNull();
|
||||
if(loginId != null) {
|
||||
logoutByLoginId(loginId);
|
||||
// 清除cookie
|
||||
// 如果连token都没有,那么无需执行任何操作
|
||||
String tokenValue = getTokenValue();
|
||||
if(tokenValue == null) {
|
||||
return;
|
||||
}
|
||||
// 如果打开了cookie模式,第一步,先把cookie清除掉
|
||||
if(SaTokenManager.getConfig().getIsReadCookie() == true){
|
||||
SaCookieUtil.delCookie(SpringMvcUtil.getRequest(), SpringMvcUtil.getResponse(), getKeyTokenName());
|
||||
SaTokenManager.getSaCookieOper().delCookie(SaTokenManager.getSta().getCurrRequest(), SaTokenManager.getSta().getResponse(), getTokenName());
|
||||
}
|
||||
// 尝试从db中获取loginId值
|
||||
String loginId = SaTokenManager.getDao().getValue(getKeyTokenValue(tokenValue));
|
||||
// 如果根本查不到loginId,那么也无需执行任何操作
|
||||
if(loginId == null) {
|
||||
return;
|
||||
}
|
||||
// 如果已经被顶替或已过期,那么只删除此token即可
|
||||
if(loginId.equals(NotLoginException.BE_REPLACED) || loginId.equals(NotLoginException.TOKEN_TIMEOUT)) {
|
||||
return;
|
||||
}
|
||||
// 至此,已经是一个正常的loginId,开始三清
|
||||
logoutByLoginId(loginId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,7 +196,6 @@ public class StpLogic {
|
||||
SaTokenManager.getDao().delKey(getKeyTokenValue(tokenValue)); // 清除token-id键值对
|
||||
SaTokenManager.getDao().delKey(getKeyLoginId(loginId)); // 清除id-token键值对
|
||||
SaTokenManager.getDao().delKey(getKeySession(loginId)); // 清除其session
|
||||
// SaCookieUtil.delCookie(SpringMVCUtil.getRequest(), SpringMVCUtil.getResponse(), getKey_tokenName()); // 清除cookie
|
||||
}
|
||||
|
||||
// 查询相关
|
||||
@@ -188,6 +205,7 @@ public class StpLogic {
|
||||
* @return 是否已登录
|
||||
*/
|
||||
public boolean isLogin() {
|
||||
// 判断条件:不为null,并且不在异常项集合里
|
||||
return getLoginIdDefaultNull() != null;
|
||||
}
|
||||
|
||||
@@ -203,10 +221,25 @@ public class StpLogic {
|
||||
* @return .
|
||||
*/
|
||||
public Object getLoginId() {
|
||||
Object loginId = getLoginIdDefaultNull();
|
||||
if(loginId == null) {
|
||||
throw new NotLoginException(this.loginKey);
|
||||
// 如果获取不到token,则抛出:无token
|
||||
String tokenValue = getTokenValue();
|
||||
if(tokenValue == null) {
|
||||
throw new NotLoginException(loginKey, NotLoginException.NOT_TOKEN);
|
||||
}
|
||||
// 查找此token对应loginId, 则抛出:无效token
|
||||
String loginId = SaTokenManager.getDao().getValue(getKeyTokenValue(tokenValue));
|
||||
if(loginId == null) {
|
||||
throw new NotLoginException(loginKey, NotLoginException.INVALID_TOKEN);
|
||||
}
|
||||
// 如果是已经被顶替下去了, 则抛出:已被顶下线
|
||||
if(loginId.equals(NotLoginException.BE_REPLACED)) {
|
||||
throw new NotLoginException(loginKey, NotLoginException.BE_REPLACED);
|
||||
}
|
||||
// 如果是已经过期,则抛出已经过期
|
||||
if(loginId.equals(NotLoginException.TOKEN_TIMEOUT)) {
|
||||
throw new NotLoginException(loginKey, NotLoginException.TOKEN_TIMEOUT);
|
||||
}
|
||||
// 至此,返回loginId
|
||||
return loginId;
|
||||
}
|
||||
|
||||
@@ -218,9 +251,11 @@ public class StpLogic {
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T>T getLoginId(T defaultValue) {
|
||||
Object loginId = getLoginIdDefaultNull();
|
||||
// 如果loginId为null,则返回默认值
|
||||
if(loginId == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
// 开始尝试类型转换,只尝试三种类型:int、long、String
|
||||
if(defaultValue instanceof Integer) {
|
||||
return (T)Integer.valueOf(loginId.toString());
|
||||
}
|
||||
@@ -235,18 +270,22 @@ public class StpLogic {
|
||||
|
||||
/**
|
||||
* 获取当前会话登录id, 如果未登录,则返回null
|
||||
* @return
|
||||
* @return .
|
||||
*/
|
||||
public Object getLoginIdDefaultNull() {
|
||||
// 如果连token都是空的,则直接返回
|
||||
String tokenValue = getTokenValue();
|
||||
if(tokenValue != null) {
|
||||
Object loginId = SaTokenManager.getDao().getValue(getKeyTokenValue(tokenValue));
|
||||
if(loginId != null) {
|
||||
return loginId;
|
||||
}
|
||||
}
|
||||
if(tokenValue == null) {
|
||||
return null;
|
||||
}
|
||||
// loginId为null或者在异常项里面,均视为未登录
|
||||
Object loginId = SaTokenManager.getDao().getValue(getKeyTokenValue(tokenValue));
|
||||
if(loginId == null || NotLoginException.ABNORMAL_LIST.contains(loginId)) {
|
||||
return null;
|
||||
}
|
||||
// 执行到此,证明loginId已经是个正常的账号id了
|
||||
return loginId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话登录id, 并转换为String
|
||||
@@ -328,7 +367,7 @@ public class StpLogic {
|
||||
* @return .
|
||||
*/
|
||||
public SaSession getSessionByLoginId(Object loginId) {
|
||||
return getSessionByLoginId(getKeySession(loginId), false);
|
||||
return getSessionByLoginId(loginId, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -336,7 +375,7 @@ public class StpLogic {
|
||||
* @return
|
||||
*/
|
||||
public SaSession getSession() {
|
||||
return getSessionBySessionId(getKeySession(getLoginId()), true);
|
||||
return getSessionByLoginId(getLoginId());
|
||||
}
|
||||
|
||||
|
||||
|
@@ -21,6 +21,13 @@ public class StpUtil {
|
||||
|
||||
// =================== 获取token 相关 ===================
|
||||
|
||||
/**
|
||||
* 返回token名称
|
||||
* @return 此StpLogic的token名称
|
||||
*/
|
||||
public static String getTokenName() {
|
||||
return stpLogic.getTokenName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前tokenValue
|
||||
|
@@ -4,27 +4,26 @@ import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
/**
|
||||
* cookie工具类
|
||||
* cookie操作工具类
|
||||
*
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaCookieUtil {
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定cookie .
|
||||
*
|
||||
* @param request .
|
||||
* @param cookieName .
|
||||
* @return .
|
||||
*/
|
||||
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())) {
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie != null && cookieName.equals(cookie.getName())) {
|
||||
return cookie;
|
||||
}
|
||||
}
|
||||
@@ -32,18 +31,18 @@ public class SaCookieUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加cookie
|
||||
*
|
||||
* @param response .
|
||||
* @param name .
|
||||
* @param value .
|
||||
* @param path .
|
||||
* @param timeout .
|
||||
*/
|
||||
public static void addCookie(HttpServletResponse response,String name,String value,String path,int timeout) {
|
||||
public static void addCookie(HttpServletResponse response, String name, String value, String path, int timeout) {
|
||||
Cookie cookie = new Cookie(name, value);
|
||||
if(path == null) {
|
||||
if (path == null) {
|
||||
path = "/";
|
||||
}
|
||||
cookie.setPath(path);
|
||||
@@ -51,45 +50,44 @@ public class SaCookieUtil {
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除cookie .
|
||||
*
|
||||
* @param request .
|
||||
* @param response .
|
||||
* @param name .
|
||||
*/
|
||||
public static void delCookie(HttpServletRequest request,HttpServletResponse response,String name) {
|
||||
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);
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie != null && (name).equals(cookie.getName())) {
|
||||
addCookie(response, name, null, null, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改cookie的value值
|
||||
*
|
||||
* @param request .
|
||||
* @param response .
|
||||
* @param name .
|
||||
* @param value .
|
||||
*/
|
||||
public static void updateCookie(HttpServletRequest request,HttpServletResponse response,String name,String 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());
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie != null && (name).equals(cookie.getName())) {
|
||||
addCookie(response, name, value, cookie.getPath(), cookie.getMaxAge());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@@ -19,7 +19,6 @@ 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.JdkSerializationRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -29,7 +28,7 @@ import cn.dev33.satoken.session.SaSession;
|
||||
/**
|
||||
* sa-token持久层的实现类 , 基于redis
|
||||
*/
|
||||
@Component // 保证此类被springboot扫描,即可完成sa-token与redis的集成
|
||||
@Component // 打开此注解,保证此类被springboot扫描,即可完成sa-token与redis的集成
|
||||
public class SaTokenDaoRedis implements SaTokenDao {
|
||||
|
||||
|
||||
@@ -42,10 +41,8 @@ public class SaTokenDaoRedis implements SaTokenDao {
|
||||
@Autowired
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void setRedisTemplate(RedisTemplate redisTemplate) {
|
||||
RedisSerializer stringSerializer = new StringRedisSerializer();
|
||||
redisTemplate.setKeySerializer(stringSerializer);
|
||||
JdkSerializationRedisSerializer jrSerializer = new JdkSerializationRedisSerializer();
|
||||
redisTemplate.setValueSerializer(jrSerializer);
|
||||
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
@@ -62,6 +59,16 @@ public class SaTokenDaoRedis implements SaTokenDao {
|
||||
stringRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
// 更新指定key-value键值对 (过期时间取原来的值)
|
||||
@Override
|
||||
public void updateValue(String key, String value) {
|
||||
long expire = redisTemplate.getExpire(key);
|
||||
if(expire == -2) { // -2 = 无此键
|
||||
return;
|
||||
}
|
||||
stringRedisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
// 删除一个指定的key
|
||||
@Override
|
||||
public void delKey(String key) {
|
||||
@@ -93,12 +100,10 @@ public class SaTokenDaoRedis implements SaTokenDao {
|
||||
|
||||
// 删除一个指定的session
|
||||
@Override
|
||||
public void delSaSession(String sessionId) {
|
||||
public void deleteSaSession(String sessionId) {
|
||||
redisTemplate.delete(sessionId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user