mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-05-04 12:47:55 +08:00
增加Cookie模式的secure、httpOnly、sameSite等配置
This commit is contained in:
parent
cf6632df79
commit
643118177a
@ -0,0 +1,122 @@
|
|||||||
|
package cn.dev33.satoken.config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sa-Token Cookie写入 相关配置
|
||||||
|
* @author kong
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SaCookieConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 域(写入Cookie时显式指定的作用域, 常用于单点登录二级域名共享Cookie的场景)
|
||||||
|
*/
|
||||||
|
private String domain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径
|
||||||
|
*/
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否只在 https 协议下有效
|
||||||
|
*/
|
||||||
|
private Boolean secure = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否禁止 js 操作 Cookie
|
||||||
|
*/
|
||||||
|
private Boolean httpOnly = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方限制级别(Strict=完全禁止,Lax=部分允许,None=不限制)
|
||||||
|
*/
|
||||||
|
private String sameSite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 域 (写入Cookie时显式指定的作用域, 常用于单点登录二级域名共享Cookie的场景)
|
||||||
|
*/
|
||||||
|
public String getDomain() {
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param domain 域 (写入Cookie时显式指定的作用域, 常用于单点登录二级域名共享Cookie的场景)
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaCookieConfig setDomain(String domain) {
|
||||||
|
this.domain = domain;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 路径
|
||||||
|
*/
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param path 路径
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaCookieConfig setPath(String path) {
|
||||||
|
this.path = path;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 是否只在 https 协议下有效
|
||||||
|
*/
|
||||||
|
public Boolean getSecure() {
|
||||||
|
return secure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param secure 是否只在 https 协议下有效
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaCookieConfig setSecure(Boolean secure) {
|
||||||
|
this.secure = secure;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 是否禁止 js 操作 Cookie
|
||||||
|
*/
|
||||||
|
public Boolean getHttpOnly() {
|
||||||
|
return httpOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param httpOnly 是否禁止 js 操作 Cookie
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaCookieConfig setHttpOnly(Boolean httpOnly) {
|
||||||
|
this.httpOnly = httpOnly;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 第三方限制级别(Strict=完全禁止,Lax=部分允许,None=不限制)
|
||||||
|
*/
|
||||||
|
public String getSameSite() {
|
||||||
|
return sameSite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sameSite 第三方限制级别(Strict=完全禁止,Lax=部分允许,None=不限制)
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaCookieConfig setSameSite(String sameSite) {
|
||||||
|
this.sameSite = sameSite;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// toString
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SaCookieConfig [domain=" + domain + ", path=" + path + ", secure=" + secure + ", httpOnly=" + httpOnly
|
||||||
|
+ ", sameSite=" + sameSite + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -41,12 +41,6 @@ public class SaTokenConfig implements Serializable {
|
|||||||
/** 是否尝试从cookie里读取token */
|
/** 是否尝试从cookie里读取token */
|
||||||
private Boolean isReadCookie = true;
|
private Boolean isReadCookie = true;
|
||||||
|
|
||||||
/** 使用Cookie时,是否为HttpOnly */
|
|
||||||
private Boolean isCookieHttpOnly = false;
|
|
||||||
|
|
||||||
/** 使用Cookie时,是否为Secure */
|
|
||||||
private Boolean isCookieSecure = false;
|
|
||||||
|
|
||||||
/** token风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik) */
|
/** token风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik) */
|
||||||
private String tokenStyle = "uuid";
|
private String tokenStyle = "uuid";
|
||||||
|
|
||||||
@ -59,9 +53,6 @@ public class SaTokenConfig implements Serializable {
|
|||||||
/** 是否打开自动续签 (如果此值为true, 框架会在每次直接或间接调用getLoginId()时进行一次过期检查与续签操作) */
|
/** 是否打开自动续签 (如果此值为true, 框架会在每次直接或间接调用getLoginId()时进行一次过期检查与续签操作) */
|
||||||
private Boolean autoRenew = true;
|
private Boolean autoRenew = true;
|
||||||
|
|
||||||
/** 写入Cookie时显式指定的作用域, 常用于单点登录二级域名共享Cookie的场景 */
|
|
||||||
private String cookieDomain;
|
|
||||||
|
|
||||||
/** token前缀, 格式样例(satoken: Bearer xxxx-xxxx-xxxx-xxxx) */
|
/** token前缀, 格式样例(satoken: Bearer xxxx-xxxx-xxxx-xxxx) */
|
||||||
private String tokenPrefix;
|
private String tokenPrefix;
|
||||||
|
|
||||||
@ -90,6 +81,11 @@ public class SaTokenConfig implements Serializable {
|
|||||||
private String currDomain;
|
private String currDomain;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cookie配置对象
|
||||||
|
*/
|
||||||
|
public SaCookieConfig cookie = new SaCookieConfig();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SSO单点登录配置对象
|
* SSO单点登录配置对象
|
||||||
*/
|
*/
|
||||||
@ -226,38 +222,6 @@ public class SaTokenConfig implements Serializable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return 使用Cookie时,是否为HttpOnly
|
|
||||||
*/
|
|
||||||
public Boolean getIsCookieHttpOnly() {
|
|
||||||
return isCookieHttpOnly;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param isCookieHttpOnly 使用Cookie时,是否为HttpOnly
|
|
||||||
* @return 对象自身
|
|
||||||
*/
|
|
||||||
public SaTokenConfig setIsCookieHttpOnly(Boolean isCookieHttpOnly) {
|
|
||||||
this.isCookieHttpOnly = isCookieHttpOnly;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return 使用Cookie时,是否为Secure
|
|
||||||
*/
|
|
||||||
public Boolean getIsCookieSecure() {
|
|
||||||
return isCookieSecure;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param isCookieSecure 使用Cookie时,是否为Secure
|
|
||||||
* @return 对象自身
|
|
||||||
*/
|
|
||||||
public SaTokenConfig setIsCookieSecure(Boolean isCookieSecure) {
|
|
||||||
this.isCookieSecure = isCookieSecure;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return token风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
* @return token风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
*/
|
*/
|
||||||
@ -324,22 +288,6 @@ public class SaTokenConfig implements Serializable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return 写入Cookie时显式指定的作用域, 常用于单点登录二级域名共享Cookie的场景
|
|
||||||
*/
|
|
||||||
public String getCookieDomain() {
|
|
||||||
return cookieDomain;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param cookieDomain 写入Cookie时显式指定的作用域, 常用于单点登录二级域名共享Cookie的场景
|
|
||||||
* @return 对象自身
|
|
||||||
*/
|
|
||||||
public SaTokenConfig setCookieDomain(String cookieDomain) {
|
|
||||||
this.cookieDomain = cookieDomain;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return token前缀, 格式样例(satoken: Bearer xxxx-xxxx-xxxx-xxxx)
|
* @return token前缀, 格式样例(satoken: Bearer xxxx-xxxx-xxxx-xxxx)
|
||||||
*/
|
*/
|
||||||
@ -461,23 +409,54 @@ public class SaTokenConfig implements Serializable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param sso SSO单点登录配置对象
|
* @param sso SSO单点登录配置对象
|
||||||
|
* @return 对象自身
|
||||||
*/
|
*/
|
||||||
public void setSso(SaSsoConfig sso) {
|
public SaTokenConfig setSso(SaSsoConfig sso) {
|
||||||
this.sso = sso;
|
this.sso = sso;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Cookie 全局配置对象
|
||||||
|
*/
|
||||||
|
public SaCookieConfig getCookie() {
|
||||||
|
return cookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param cookie Cookie 全局配置对象
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaTokenConfig setCookie(SaCookieConfig cookie) {
|
||||||
|
this.cookie = cookie;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "SaTokenConfig [tokenName=" + tokenName + ", timeout=" + timeout + ", activityTimeout=" + activityTimeout
|
return "SaTokenConfig ["
|
||||||
+ ", isConcurrent=" + isConcurrent + ", isShare=" + isShare + ", isReadBody=" + isReadBody
|
+ "tokenName=" + tokenName
|
||||||
+ ", isReadHead=" + isReadHead + ", isReadCookie=" + isReadCookie
|
+ ", timeout=" + timeout
|
||||||
+ ", isCookieHttpOnly=" + isCookieHttpOnly + ", isCookieSecure=" + isCookieSecure
|
+ ", activityTimeout=" + activityTimeout
|
||||||
|
+ ", isConcurrent=" + isConcurrent
|
||||||
|
+ ", isShare=" + isShare
|
||||||
|
+ ", isReadBody=" + isReadBody
|
||||||
|
+ ", isReadHead=" + isReadHead
|
||||||
|
+ ", isReadCookie=" + isReadCookie
|
||||||
+ ", tokenStyle=" + tokenStyle
|
+ ", tokenStyle=" + tokenStyle
|
||||||
+ ", dataRefreshPeriod=" + dataRefreshPeriod + ", tokenSessionCheckLogin=" + tokenSessionCheckLogin
|
+ ", dataRefreshPeriod=" + dataRefreshPeriod
|
||||||
+ ", autoRenew=" + autoRenew + ", cookieDomain=" + cookieDomain + ", tokenPrefix=" + tokenPrefix
|
+ ", tokenSessionCheckLogin=" + tokenSessionCheckLogin
|
||||||
+ ", isPrint=" + isPrint + ", isLog=" + isLog + ", jwtSecretKey=" + jwtSecretKey + ", idTokenTimeout="
|
+ ", autoRenew=" + autoRenew
|
||||||
+ idTokenTimeout + ", basic=" + basic + ", currDomain=" + currDomain + ", sso=" + sso + "]";
|
+ ", tokenPrefix=" + tokenPrefix
|
||||||
|
+ ", isPrint=" + isPrint
|
||||||
|
+ ", isLog=" + isLog
|
||||||
|
+ ", jwtSecretKey=" + jwtSecretKey
|
||||||
|
+ ", idTokenTimeout=" + idTokenTimeout
|
||||||
|
+ ", basic=" + basic
|
||||||
|
+ ", currDomain=" + currDomain
|
||||||
|
+ ", sso=" + sso
|
||||||
|
+ ", cookie=" + cookie
|
||||||
|
+ "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -503,4 +482,25 @@ public class SaTokenConfig implements Serializable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <h1> 本函数设计已过时,未来版本可能移除此函数,请及时更换为 getCookie().getDomain() ,使用方式保持不变 </h1>
|
||||||
|
* @return 写入Cookie时显式指定的作用域, 常用于单点登录二级域名共享Cookie的场景
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public String getCookieDomain() {
|
||||||
|
return getCookie().getDomain();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <h1> 本函数设计已过时,未来版本可能移除此函数,请及时更换为 getCookie().setDomain() ,使用方式保持不变 </h1>
|
||||||
|
* @param cookieDomain 写入Cookie时显式指定的作用域, 常用于单点登录二级域名共享Cookie的场景
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public SaTokenConfig setCookieDomain(String cookieDomain) {
|
||||||
|
this.getCookie().setDomain(cookieDomain);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,275 @@
|
|||||||
|
package cn.dev33.satoken.context.model;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.exception.SaTokenException;
|
||||||
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cookie Model
|
||||||
|
* @author kong
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SaCookie {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入响应头时使用的key
|
||||||
|
*/
|
||||||
|
public static final String HEADER_NAME = "Set-Cookie";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 值
|
||||||
|
*/
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 有效时长 (单位:秒),-1代表为临时Cookie 浏览器关闭后自动删除
|
||||||
|
*/
|
||||||
|
private int maxAge = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 域
|
||||||
|
*/
|
||||||
|
private String domain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径
|
||||||
|
*/
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否只在 https 协议下有效
|
||||||
|
*/
|
||||||
|
private Boolean secure = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否禁止 js 操作 Cookie
|
||||||
|
*/
|
||||||
|
private Boolean httpOnly = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方限制级别(Strict=完全禁止,Lax=部分允许,None=不限制)
|
||||||
|
*/
|
||||||
|
private String sameSite;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造一个
|
||||||
|
*/
|
||||||
|
public SaCookie() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造一个
|
||||||
|
* @param name 名字
|
||||||
|
* @param value 值
|
||||||
|
*/
|
||||||
|
public SaCookie(String name, String value) {
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 名称
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name 名称
|
||||||
|
*/
|
||||||
|
public SaCookie setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 值
|
||||||
|
*/
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param value 值
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaCookie setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 有效时长 (单位:秒),-1代表为临时Cookie 浏览器关闭后自动删除
|
||||||
|
*/
|
||||||
|
public int getMaxAge() {
|
||||||
|
return maxAge;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param maxAge 有效时长 (单位:秒),-1代表为临时Cookie 浏览器关闭后自动删除
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaCookie setMaxAge(int maxAge) {
|
||||||
|
this.maxAge = maxAge;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 域
|
||||||
|
*/
|
||||||
|
public String getDomain() {
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param domain 域
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaCookie setDomain(String domain) {
|
||||||
|
this.domain = domain;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 路径
|
||||||
|
*/
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param path 路径
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaCookie setPath(String path) {
|
||||||
|
this.path = path;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 是否只在 https 协议下有效
|
||||||
|
*/
|
||||||
|
public Boolean getSecure() {
|
||||||
|
return secure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param secure 是否只在 https 协议下有效
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaCookie setSecure(Boolean secure) {
|
||||||
|
this.secure = secure;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 是否禁止 js 操作 Cookie
|
||||||
|
*/
|
||||||
|
public Boolean getHttpOnly() {
|
||||||
|
return httpOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param httpOnly 是否禁止 js 操作 Cookie
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaCookie setHttpOnly(Boolean httpOnly) {
|
||||||
|
this.httpOnly = httpOnly;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 第三方限制级别(Strict=完全禁止,Lax=部分允许,None=不限制)
|
||||||
|
*/
|
||||||
|
public String getSameSite() {
|
||||||
|
return sameSite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sameSite 第三方限制级别(Strict=完全禁止,Lax=部分允许,None=不限制)
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaCookie setSameSite(String sameSite) {
|
||||||
|
this.sameSite = sameSite;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// toString
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SaCookie [name=" + name + ", value=" + value + ", maxAge=" + maxAge + ", domain=" + domain + ", path=" + path
|
||||||
|
+ ", secure=" + secure + ", httpOnly=" + httpOnly + ", sameSite="
|
||||||
|
+ sameSite + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建一下
|
||||||
|
*/
|
||||||
|
public void builde() {
|
||||||
|
if(path == null) {
|
||||||
|
path = "/";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换为响应头 Set-Cookie 参数需要的值
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public String toHeaderValue() {
|
||||||
|
this.builde();
|
||||||
|
|
||||||
|
if(SaFoxUtil.isEmpty(name)) {
|
||||||
|
throw new SaTokenException("name不能为空");
|
||||||
|
}
|
||||||
|
if(value != null && value.indexOf(";") > -1) {
|
||||||
|
throw new SaTokenException("无效Value:" + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set-Cookie: name=value; Max-Age=100000; Expires=Tue, 05-Oct-2021 20:28:17 GMT; Domain=localhost; Path=/; Secure; HttpOnly; SameSite=Lax
|
||||||
|
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
sb.append(name + "=" + value);
|
||||||
|
|
||||||
|
if(maxAge >= 0) {
|
||||||
|
sb.append("; Max-Age=" + maxAge);
|
||||||
|
String expires;
|
||||||
|
if(maxAge == 0) {
|
||||||
|
expires = Instant.EPOCH.atOffset(ZoneOffset.UTC).format(DateTimeFormatter.RFC_1123_DATE_TIME);
|
||||||
|
} else {
|
||||||
|
expires = OffsetDateTime.now().plusSeconds(maxAge).format(DateTimeFormatter.RFC_1123_DATE_TIME);
|
||||||
|
}
|
||||||
|
sb.append("; Expires=" + expires);
|
||||||
|
}
|
||||||
|
if(SaFoxUtil.isEmpty(domain) == false) {
|
||||||
|
sb.append("; Domain=" + domain);
|
||||||
|
}
|
||||||
|
if(SaFoxUtil.isEmpty(path) == false) {
|
||||||
|
sb.append("; Path=" + path);
|
||||||
|
}
|
||||||
|
if(secure) {
|
||||||
|
sb.append("; Secure");
|
||||||
|
}
|
||||||
|
if(httpOnly) {
|
||||||
|
sb.append("; HttpOnly");
|
||||||
|
}
|
||||||
|
if(SaFoxUtil.isEmpty(sameSite) == false) {
|
||||||
|
sb.append("; sameSite=" + sameSite);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -17,7 +17,9 @@ public interface SaResponse {
|
|||||||
* 删除指定Cookie
|
* 删除指定Cookie
|
||||||
* @param name Cookie名称
|
* @param name Cookie名称
|
||||||
*/
|
*/
|
||||||
public void deleteCookie(String name);
|
public default void deleteCookie(String name) {
|
||||||
|
addCookie(name, null, null, null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 写入指定Cookie
|
* 写入指定Cookie
|
||||||
@ -28,20 +30,16 @@ public interface SaResponse {
|
|||||||
* @param timeout 过期时间 (秒)
|
* @param timeout 过期时间 (秒)
|
||||||
*/
|
*/
|
||||||
public default void addCookie(String name, String value, String path, String domain, int timeout) {
|
public default void addCookie(String name, String value, String path, String domain, int timeout) {
|
||||||
this.addCookie(name, value, path, domain, timeout, false, false);
|
this.addCookie(new SaCookie(name, value).setPath(path).setDomain(domain).setMaxAge(timeout));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 写入指定Cookie
|
* 写入指定Cookie
|
||||||
* @param name Cookie名称
|
* @param cookie Cookie-Model
|
||||||
* @param value Cookie值
|
|
||||||
* @param path Cookie路径
|
|
||||||
* @param domain Cookie的作用域
|
|
||||||
* @param timeout 过期时间 (秒)
|
|
||||||
* @param isHttpOnly 是否为HttpOnly
|
|
||||||
* @param isSecure 是否为Secure
|
|
||||||
*/
|
*/
|
||||||
public void addCookie(String name, String value, String path, String domain, int timeout, boolean isHttpOnly, boolean isSecure);
|
public default void addCookie(SaCookie cookie) {
|
||||||
|
this.addHeader(SaCookie.HEADER_NAME, cookie.toHeaderValue());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置响应状态码
|
* 设置响应状态码
|
||||||
@ -58,6 +56,14 @@ public interface SaResponse {
|
|||||||
*/
|
*/
|
||||||
public SaResponse setHeader(String name, String value);
|
public SaResponse setHeader(String name, String value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在响应头里添加一个值
|
||||||
|
* @param name 名字
|
||||||
|
* @param value 值
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaResponse addHeader(String name, String value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在响应头写入 [Server] 服务器名称
|
* 在响应头写入 [Server] 服务器名称
|
||||||
* @param value 服务器名称
|
* @param value 服务器名称
|
||||||
|
@ -12,10 +12,11 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
|
|||||||
import cn.dev33.satoken.annotation.SaCheckRole;
|
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||||
import cn.dev33.satoken.annotation.SaCheckSafe;
|
import cn.dev33.satoken.annotation.SaCheckSafe;
|
||||||
import cn.dev33.satoken.annotation.SaMode;
|
import cn.dev33.satoken.annotation.SaMode;
|
||||||
|
import cn.dev33.satoken.config.SaCookieConfig;
|
||||||
import cn.dev33.satoken.config.SaTokenConfig;
|
import cn.dev33.satoken.config.SaTokenConfig;
|
||||||
import cn.dev33.satoken.context.SaHolder;
|
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.SaRequest;
|
||||||
import cn.dev33.satoken.context.model.SaResponse;
|
|
||||||
import cn.dev33.satoken.context.model.SaStorage;
|
import cn.dev33.satoken.context.model.SaStorage;
|
||||||
import cn.dev33.satoken.dao.SaTokenDao;
|
import cn.dev33.satoken.dao.SaTokenDao;
|
||||||
import cn.dev33.satoken.exception.DisableLoginException;
|
import cn.dev33.satoken.exception.DisableLoginException;
|
||||||
@ -110,14 +111,32 @@ public class StpLogic {
|
|||||||
storage.set(splicingKeyJustCreatedSave(), tokenValue);
|
storage.set(splicingKeyJustCreatedSave(), tokenValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 将token保存到[Cookie]里
|
// 2. 将 Token 保存到 [Cookie] 里
|
||||||
if (config.getIsReadCookie()) {
|
if (config.getIsReadCookie()) {
|
||||||
SaResponse response = SaHolder.getResponse();
|
setTokenValueToCookie(tokenValue, cookieTimeout);
|
||||||
response.addCookie(getTokenName(), tokenValue, "/",
|
|
||||||
config.getCookieDomain(), cookieTimeout, config.getIsCookieHttpOnly(), config.getIsCookieSecure());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 Token 保存到 [Cookie] 里
|
||||||
|
* @param tokenValue token值
|
||||||
|
* @param cookieTimeout Cookie存活时间(秒)
|
||||||
|
*/
|
||||||
|
public void setTokenValueToCookie(String tokenValue, int cookieTimeout){
|
||||||
|
SaCookieConfig cfg = getConfig().getCookie();
|
||||||
|
SaCookie cookie = new SaCookie()
|
||||||
|
.setName(getTokenName())
|
||||||
|
.setValue(tokenValue)
|
||||||
|
.setMaxAge(cookieTimeout)
|
||||||
|
.setDomain(cfg.getDomain())
|
||||||
|
.setPath(cfg.getPath())
|
||||||
|
.setSecure(cfg.getSecure())
|
||||||
|
.setHttpOnly(cfg.getHttpOnly())
|
||||||
|
.setSameSite(cfg.getSameSite())
|
||||||
|
;
|
||||||
|
SaHolder.getResponse().addCookie(cookie);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前TokenValue
|
* 获取当前TokenValue
|
||||||
* @return 当前tokenValue
|
* @return 当前tokenValue
|
||||||
|
@ -133,7 +133,7 @@ public class SaTokenJwtUtil {
|
|||||||
String tokenValue = createTokenValue(loginId);
|
String tokenValue = createTokenValue(loginId);
|
||||||
storage.set(splicingKeyJustCreatedSave(), tokenValue); // 将token保存到本次request里
|
storage.set(splicingKeyJustCreatedSave(), tokenValue); // 将token保存到本次request里
|
||||||
if(config.getIsReadCookie() == true){ // cookie注入
|
if(config.getIsReadCookie() == true){ // cookie注入
|
||||||
SaManager.getSaTokenContext().getResponse().addCookie(getTokenName(), tokenValue, "/", config.getCookieDomain(), (int)config.getTimeout());
|
SaManager.getSaTokenContext().getResponse().addCookie(getTokenName(), tokenValue, "/", config.getCookie().getDomain(), (int)config.getTimeout());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
|||||||
@Override
|
@Override
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
// 注册注解拦截器
|
// 注册注解拦截器
|
||||||
registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**").excludePathPatterns("");
|
registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -239,7 +239,7 @@ public class TestController {
|
|||||||
// 测试 浏览器访问: http://localhost:8081/test/test
|
// 测试 浏览器访问: http://localhost:8081/test/test
|
||||||
@RequestMapping("test")
|
@RequestMapping("test")
|
||||||
public AjaxJson test() {
|
public AjaxJson test() {
|
||||||
System.out.println("进来了");
|
System.out.println("------------进来了");
|
||||||
return AjaxJson.getSuccess();
|
return AjaxJson.getSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,6 +249,4 @@ public class TestController {
|
|||||||
return AjaxJson.getSuccess();
|
return AjaxJson.getSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,9 @@ package cn.dev33.satoken.reactor.model;
|
|||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseCookie;
|
|
||||||
import org.springframework.http.ResponseCookie.ResponseCookieBuilder;
|
|
||||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||||
|
|
||||||
import cn.dev33.satoken.context.model.SaResponse;
|
import cn.dev33.satoken.context.model.SaResponse;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Response for Reactor
|
* Response for Reactor
|
||||||
@ -38,43 +35,6 @@ public class SaResponseForReactor implements SaResponse {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除指定Cookie
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void deleteCookie(String name) {
|
|
||||||
addCookie(name, null, null, null, 0, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 写入指定Cookie
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void addCookie(String name, String value, String path, String domain, int timeout, boolean isHttpOnly, boolean isSecure) {
|
|
||||||
// 构建CookieBuilder
|
|
||||||
ResponseCookieBuilder builder = ResponseCookie.from(name, value)
|
|
||||||
.domain(domain)
|
|
||||||
.path(path)
|
|
||||||
.maxAge(timeout)
|
|
||||||
.httpOnly(isHttpOnly)
|
|
||||||
.secure(isSecure)
|
|
||||||
;
|
|
||||||
|
|
||||||
// set path
|
|
||||||
if(SaFoxUtil.isEmpty(path) == true) {
|
|
||||||
path = "/";
|
|
||||||
}
|
|
||||||
builder.path(path);
|
|
||||||
|
|
||||||
// set domain
|
|
||||||
if(SaFoxUtil.isEmpty(domain) == false) {
|
|
||||||
builder.domain(domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 写入Cookie
|
|
||||||
response.addCookie(builder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置响应状态码
|
* 设置响应状态码
|
||||||
*/
|
*/
|
||||||
@ -93,6 +53,17 @@ public class SaResponseForReactor implements SaResponse {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在响应头里添加一个值
|
||||||
|
* @param name 名字
|
||||||
|
* @param value 值
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaResponse addHeader(String name, String value) {
|
||||||
|
response.getHeaders().add(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重定向
|
* 重定向
|
||||||
*/
|
*/
|
||||||
|
@ -2,12 +2,10 @@ package cn.dev33.satoken.servlet.model;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import javax.servlet.http.Cookie;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import cn.dev33.satoken.context.model.SaResponse;
|
import cn.dev33.satoken.context.model.SaResponse;
|
||||||
import cn.dev33.satoken.exception.SaTokenException;
|
import cn.dev33.satoken.exception.SaTokenException;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Response for Servlet
|
* Response for Servlet
|
||||||
@ -37,33 +35,6 @@ public class SaResponseForServlet implements SaResponse {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除指定Cookie
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void deleteCookie(String name) {
|
|
||||||
addCookie(name, null, null, null, 0, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 写入指定Cookie
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void addCookie(String name, String value, String path, String domain, int timeout, boolean isHttpOnly, boolean isSecure) {
|
|
||||||
Cookie cookie = new Cookie(name, value);
|
|
||||||
if(SaFoxUtil.isEmpty(path) == true) {
|
|
||||||
path = "/";
|
|
||||||
}
|
|
||||||
if(SaFoxUtil.isEmpty(domain) == false) {
|
|
||||||
cookie.setDomain(domain);
|
|
||||||
}
|
|
||||||
cookie.setPath(path);
|
|
||||||
cookie.setMaxAge(timeout);
|
|
||||||
cookie.setHttpOnly(isHttpOnly);
|
|
||||||
cookie.setSecure(isSecure);
|
|
||||||
response.addCookie(cookie);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置响应状态码
|
* 设置响应状态码
|
||||||
*/
|
*/
|
||||||
@ -82,6 +53,17 @@ public class SaResponseForServlet implements SaResponse {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在响应头里添加一个值
|
||||||
|
* @param name 名字
|
||||||
|
* @param value 值
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaResponse addHeader(String name, String value) {
|
||||||
|
response.addHeader(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重定向
|
* 重定向
|
||||||
*/
|
*/
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package cn.dev33.satoken.solon.model;
|
package cn.dev33.satoken.solon.model;
|
||||||
|
|
||||||
import org.noear.solon.Utils;
|
|
||||||
import org.noear.solon.core.handle.Context;
|
import org.noear.solon.core.handle.Context;
|
||||||
|
|
||||||
import cn.dev33.satoken.context.model.SaResponse;
|
import cn.dev33.satoken.context.model.SaResponse;
|
||||||
@ -22,20 +21,6 @@ public class SaResponseForSolon implements SaResponse {
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteCookie(String s) {
|
|
||||||
ctx.cookieRemove(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addCookie(String name, String value, String path, String domain, int timeout, boolean isHttpOnly, boolean isSecure) {
|
|
||||||
if (Utils.isNotEmpty(path)) {
|
|
||||||
path = "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.cookieSet(name, value, domain, path, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SaResponse setStatus(int sc) {
|
public SaResponse setStatus(int sc) {
|
||||||
ctx.status(sc);
|
ctx.status(sc);
|
||||||
@ -48,6 +33,17 @@ public class SaResponseForSolon implements SaResponse {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在响应头里添加一个值
|
||||||
|
* @param name 名字
|
||||||
|
* @param value 值
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaResponse addHeader(String name, String value) {
|
||||||
|
ctx.headerAdd(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object redirect(String url) {
|
public Object redirect(String url) {
|
||||||
ctx.redirect(url);
|
ctx.redirect(url);
|
||||||
|
Loading…
Reference in New Issue
Block a user