新增登录后将 Token 写入响应头的方法

This commit is contained in:
click33 2022-10-21 18:19:41 +08:00
parent fa14d98462
commit e21928183d
7 changed files with 163 additions and 21 deletions

View File

@ -46,6 +46,9 @@ public class SaTokenConfig implements Serializable {
/** 是否尝试从cookie里读取token */
private Boolean isReadCookie = true;
/** 是否在登录后将 Token 写入到响应头 */
private Boolean isWriteHeader = false;
/** token风格(默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik) */
private String tokenStyle = "uuid";
@ -240,6 +243,22 @@ public class SaTokenConfig implements Serializable {
return this;
}
/**
* @return 是否在登录后将 Token 写入到响应头
*/
public Boolean getIsWriteHeader() {
return isWriteHeader;
}
/**
* @param isWriteHeader 是否在登录后将 Token 写入到响应头
* @return 对象自身
*/
public SaTokenConfig setIsWriteHeader(Boolean isWriteHeader) {
this.isWriteHeader = isWriteHeader;
return this;
}
/**
* @return token风格(默认可取值uuidsimple-uuidrandom-32random-64random-128tik)
*/
@ -462,6 +481,7 @@ public class SaTokenConfig implements Serializable {
+ ", isReadBody=" + isReadBody
+ ", isReadHeader=" + isReadHeader
+ ", isReadCookie=" + isReadCookie
+ ", isWriteHeader=" + isWriteHeader
+ ", tokenStyle=" + tokenStyle
+ ", dataRefreshPeriod=" + dataRefreshPeriod
+ ", tokenSessionCheckLogin=" + tokenSessionCheckLogin

View File

@ -7,6 +7,11 @@ package cn.dev33.satoken.context.model;
*/
public interface SaResponse {
/**
* 指定前端可以获取到哪些响应头时使用的参数名
*/
public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers";
/**
* 获取底层源对象
* @return see note

View File

@ -16,7 +16,7 @@ public class SaLoginConfig {
/**
* @param device 此次登录的客户端设备类型
* @return SaLoginModel配置对象
* @return 登录参数 Model
*/
public static SaLoginModel setDevice(String device) {
return create().setDevice(device);
@ -24,7 +24,7 @@ public class SaLoginConfig {
/**
* @param isLastingCookie 是否为持久Cookie临时Cookie在浏览器关闭时会自动删除持久Cookie在重新打开后依然存在
* @return 对象自身
* @return 登录参数 Model
*/
public static SaLoginModel setIsLastingCookie(Boolean isLastingCookie) {
return create().setIsLastingCookie(isLastingCookie);
@ -32,7 +32,7 @@ public class SaLoginConfig {
/**
* @param timeout 指定此次登录token的有效期, 单位: 如未指定自动取全局配置的timeout值
* @return 对象自身
* @return 登录参数 Model
*/
public static SaLoginModel setTimeout(long timeout) {
return create().setTimeout(timeout);
@ -40,7 +40,7 @@ public class SaLoginConfig {
/**
* @param extraData 扩展信息只在jwt模式下生效
* @return 对象自身
* @return 登录参数 Model
*/
public static SaLoginModel setExtraData(Map<String, Object> extraData) {
return create().setExtraData(extraData);
@ -48,7 +48,7 @@ public class SaLoginConfig {
/**
* @param token 预定Token预定本次登录生成的Token值
* @return 对象自身
* @return 登录参数 Model
*/
public static SaLoginModel setToken(String token) {
return create().setToken(token);
@ -58,12 +58,20 @@ public class SaLoginConfig {
* 写入扩展数据只在jwt模式下生效
* @param key
* @param value
* @return 对象自身
* @return 登录参数 Model
*/
public static SaLoginModel setExtra(String key, Object value) {
return create().setExtra(key, value);
}
/**
* @param isWriteHeader 是否在登录后将 Token 写入到响应头
* @return 登录参数 Model
*/
public static SaLoginModel setIsWriteHeader(Boolean isWriteHeader) {
return create().setIsWriteHeader(isWriteHeader);
}
/**
* 静态方法获取一个 SaLoginModel 对象
* @return SaLoginModel 对象

View File

@ -23,7 +23,7 @@ public class SaLoginModel {
/**
* 是否为持久Cookie临时Cookie在浏览器关闭时会自动删除持久Cookie在重新打开后依然存在
*/
public Boolean isLastingCookie;
public Boolean isLastingCookie = true;
/**
* 指定此次登录token的有效期, 单位: 如未指定自动取全局配置的timeout值
@ -39,6 +39,9 @@ public class SaLoginModel {
* 预定Token预定本次登录生成的Token值
*/
public String token;
/** 是否在登录后将 Token 写入到响应头 */
private Boolean isWriteHeader;
/**
@ -58,12 +61,22 @@ public class SaLoginModel {
}
/**
* @return 参考 是否为持久Cookie临时Cookie在浏览器关闭时会自动删除持久Cookie在重新打开后依然存在
* @return 是否为持久Cookie临时Cookie在浏览器关闭时会自动删除持久Cookie在重新打开后依然存在
*/
public Boolean getIsLastingCookie() {
return isLastingCookie;
}
/**
* @return 是否为持久Cookie临时Cookie在浏览器关闭时会自动删除持久Cookie在重新打开后依然存在
*/
public Boolean getIsLastingCookieOrFalse() {
if(isLastingCookie == null) {
return false;
}
return isLastingCookie;
}
/**
* @param isLastingCookie 是否为持久Cookie临时Cookie在浏览器关闭时会自动删除持久Cookie在重新打开后依然存在
* @return 对象自身
@ -121,13 +134,45 @@ public class SaLoginModel {
return this;
}
/**
* @return 是否在登录后将 Token 写入到响应头
*/
public Boolean getIsWriteHeader() {
return isWriteHeader;
}
/**
* @return 是否在登录后将 Token 写入到响应头
*/
public Boolean getIsWriteHeaderOrFalse() {
if(isWriteHeader == null) {
return false;
}
return isWriteHeader;
}
/**
* @param isWriteHeader 是否在登录后将 Token 写入到响应头
* @return 对象自身
*/
public SaLoginModel setIsWriteHeader(Boolean isWriteHeader) {
this.isWriteHeader = isWriteHeader;
return this;
}
/*
* toString
*/
@Override
public String toString() {
return "SaLoginModel [device=" + device + ", isLastingCookie=" + isLastingCookie + ", timeout=" + timeout
+ ", extraData=" + extraData + ", token=" + token + "]";
return "SaLoginModel ["
+ "device=" + device
+ ", isLastingCookie=" + isLastingCookie
+ ", timeout=" + timeout
+ ", extraData=" + extraData
+ ", token=" + token
+ ", isWriteHeader=" + isWriteHeader
+ "]";
}
// ------ 附加方法
@ -174,9 +219,10 @@ public class SaLoginModel {
* @return Cookie时长
*/
public int getCookieTimeout() {
if(isLastingCookie == false) {
if(getIsLastingCookieOrFalse() == false) {
return -1;
}
initTimeout();
if(timeout == SaTokenDao.NEVER_EXPIRE) {
return Integer.MAX_VALUE;
}
@ -193,6 +239,15 @@ public class SaLoginModel {
return device;
}
/**
* 初始化 timeout 如果尚未配置timeout则取全局配置的值
*/
public void initTimeout() {
if(timeout == null) {
timeout = SaManager.getConfig().getTimeout();
}
}
/**
* 构建对象初始化默认值
* @return 对象自身
@ -210,12 +265,15 @@ public class SaLoginModel {
// if(device == null) {
// device = SaTokenConsts.DEFAULT_LOGIN_DEVICE;
// }
if(isLastingCookie == null) {
isLastingCookie = true;
}
// if(isLastingCookie == null) {
// isLastingCookie = true;
// }
if(timeout == null) {
timeout = config.getTimeout();
}
if(isWriteHeader == null) {
isWriteHeader = config.getIsWriteHeader();
}
return this;
}

View File

@ -17,6 +17,7 @@ import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaCookie;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.context.model.SaStorage;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.exception.ApiDisabledException;
@ -102,7 +103,7 @@ public class StpLogic {
* @param tokenValue token值
*/
public void setTokenValue(String tokenValue){
setTokenValue(tokenValue, getConfigOfCookieTimeout());
setTokenValue(tokenValue, new SaLoginModel().setTimeout(getConfig().getTimeout()));
}
/**
@ -111,17 +112,31 @@ public class StpLogic {
* @param cookieTimeout Cookie存活时间()
*/
public void setTokenValue(String tokenValue, int cookieTimeout){
setTokenValue(tokenValue, new SaLoginModel().setTimeout(cookieTimeout));
}
/**
* 在当前会话写入当前TokenValue
* @param tokenValue token值
* @param loginModel 登录参数
*/
public void setTokenValue(String tokenValue, SaLoginModel loginModel){
if(SaFoxUtil.isEmpty(tokenValue)) {
return;
}
// 1. 将token保存到[存储器]
// 1. Token 保存到 [存储器]
setTokenValueToStorage(tokenValue);
// 2. Token 保存到 [Cookie]
if (getConfig().getIsReadCookie()) {
setTokenValueToCookie(tokenValue, cookieTimeout);
setTokenValueToCookie(tokenValue, loginModel.getCookieTimeout());
}
// 3. Token 写入到响应头里
if(loginModel.getIsWriteHeaderOrFalse()) {
setTokenValueToResponseHeader(tokenValue);
}
}
@ -164,6 +179,17 @@ public class StpLogic {
;
SaHolder.getResponse().addCookie(cookie);
}
/**
* Token 写入到 [响应头]
* @param tokenValue token值
*/
public void setTokenValueToResponseHeader(String tokenValue){
String tokenName = getTokenName();
SaResponse response = SaHolder.getResponse();
response.setHeader(tokenName, tokenValue);
response.addHeader(SaResponse.ACCESS_CONTROL_EXPOSE_HEADERS, tokenName);
}
/**
* 获取当前TokenValue
@ -292,7 +318,7 @@ public class StpLogic {
String token = createLoginSession(id, loginModel);
// 2在当前客户端注入Token
setTokenValue(token, loginModel.getCookieTimeout());
setTokenValue(token, loginModel);
}
/**

View File

@ -83,7 +83,16 @@ public class StpUtil {
public static void setTokenValue(String tokenValue, int cookieTimeout){
stpLogic.setTokenValue(tokenValue, cookieTimeout);
}
/**
* 在当前会话写入当前TokenValue
* @param tokenValue token值
* @param loginModel 登录参数
*/
public static void setTokenValue(String tokenValue, SaLoginModel loginModel){
stpLogic.setTokenValue(tokenValue, loginModel);
}
/**
* 获取当前TokenValue
* @return 当前tokenValue

View File

@ -8,6 +8,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.router.SaHttpMethod;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.util.SaResult;
@ -51,7 +53,7 @@ public class SaTokenConfigure implements WebMvcConfigurer {
})
// 前置函数在每次认证函数之前执行
.setBeforeAuth(r -> {
.setBeforeAuth(obj -> {
// ---------- 设置一些安全响应头 ----------
SaHolder.getResponse()
// 服务器名称
@ -62,7 +64,21 @@ public class SaTokenConfigure implements WebMvcConfigurer {
.setHeader("X-XSS-Protection", "1; mode=block")
// 禁用浏览器内容嗅探
.setHeader("X-Content-Type-Options", "nosniff")
;
// ---------- 设置跨域响应头 ----------
// 允许指定域访问跨域资源
.setHeader("Access-Control-Allow-Origin", "*")
// 允许所有请求方式
.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
// 有效时间
.setHeader("Access-Control-Max-Age", "3600")
// 允许的header参数
.setHeader("Access-Control-Allow-Headers", "*");
// 如果是预检请求则立即返回到前端
SaRouter.match(SaHttpMethod.OPTIONS)
.free(r -> System.out.println("--------OPTIONS预检请求不做处理"))
.back();
})
;
}