sa-token使用(源码解析 + 万字)

public void setTokenValue(String tokenValue, int cookieTimeout){

SaTokenConfig config = getConfig();

// 将token保存到[存储器]里

SaStorage storage = SaHolder.getStorage();

// 判断是否配置了token前缀

String tokenPrefix = config.getTokenPrefix();

if(SaFoxUtil.isEmpty(tokenPrefix)) {

storage.set(splicingKeyJustCreatedSave(), tokenValue);

} else {

// 如果配置了token前缀,则拼接上前缀一起写入

storage.set(splicingKeyJustCreatedSave(), tokenPrefix + SaTokenConsts.TOKEN_CONNECTOR_CHAT + tokenValue);

}

// 注入Cookie

if(config.getIsReadCookie()){

SaResponse response = SaHolder.getResponse();

response.addCookie(getTokenName(), tokenValue, “/”, config.getCookieDomain(), cookieTimeout);

}

}

SaStorage是一个接口,set方法是把token存入request对象中。

关键是下面一段:

esponse.addCookie(getTokenName(), tokenValue, “/”, config.getCookieDomain(), cookieTimeout);

这句话利用cookie保存了当前登录用户的token。

谷歌浏览器查看cookie方式:右上角有三个点的按钮 - 设置

image

image

搜索localhost,找到satoken,这就是上面代码中getTokenName()方法的返回值

image

步骤 6 sa-token为什么能获取到response对象?SaHolder的秘密。。。(深挖,看不懂就跳过,没事)

===========================================================

之前我也一直想不通一个问题,sa-token用起来也太方便了吧,就这么一句话,什么都搞定了。我也不需要去关心session,也不要管HttpServletResponse啥的。

秘密就在这:

SaResponse response = SaHolder.getResponse();

SaHolder调用getResponse方法得到SaResponse, 这个SaResponse是一个接口

package cn.dev33.satoken.context.model;

/**

  • Response 包装类

  • @author kong

*/

public interface SaResponse {

/**

  • 获取底层源对象

  • @return see note

*/

public Object getSource();

/**

  • 删除指定Cookie

  • @param name Cookie名称

*/

public void deleteCookie(String name);

/**

  • 写入指定Cookie

  • @param name Cookie名称

  • @param value Cookie值

  • @param path Cookie路径

  • @param domain Cookie的作用域

  • @param timeout 过期时间 (秒)

*/

public void addCookie(String name, String value, String path, String domain, int timeout);

/**

  • 在响应头里写入一个值

  • @param name 名字

  • @param value 值

  • @return 对象自身

*/

public SaResponse setHeader(String name, String value);

/**

  • 在响应头写入 [Server] 服务器名称

  • @param value 服务器名称

  • @return 对象自身

*/

public default SaResponse setServer(String value) {

return this.setHeader(“Server”, value);

<think>好的,我现在要帮用户解决在Java项目中集成sa-token与uni-app实现单点登录的问题。首先,我需要回忆一下sa-token的相关知识。用户提到了引用[1]中的SaTokenEventCenter.registerListener,这说明sa-token有事件监听机制,可能在登录时触发某些操作。另外,用户还提到Hutool工具库,但暂时可能和SSO关系不大,先不考虑。 单点登录(SSO)的核心是多个系统共享登录状态。常见的方案有基于Token的SSO,比如用户登录一个系统后,生成一个全局的Token,其他系统验证这个Token的有效性。sa-token支持分布式会话和Token认证,所以应该可以用它来实现。 接下来,我需要确定sa-token的集成步骤。首先,用户需要在Java后端引入sa-token的依赖,比如Maven的配置。然后,配置sa-token,特别是设置不同的系统域名,因为SSO需要共享Cookie,而跨域情况下需要处理。可能需要设置Cookie的作用域为顶级域名,比如.example.com,这样所有子域名都可以访问。 然后是单点登录的逻辑。用户登录主系统后,sa-token会生成Token,并存储在Cookie中。其他子系统需要验证这个Token,所以需要有一个统一的认证中心。或者,sa-token可能已经内置了SSO的模块,需要查证一下。比如,sa-tokensa-token-sso模块,可以简化SSO的实现。 对于uni-app前端,如何处理跨域的问题?uni-app使用JavaScript,可能需要在前端请求时携带Token。如果使用Cookie,需要确保跨域请求允许携带凭证,比如设置withCredentials为true。或者,使用Token放在请求头中,每次请求时传递给后端。 另外,需要考虑安全性,比如Token的加密传输、HTTPS的使用,防止中间人攻击。同时,Token的有效期和刷新机制也需要处理,避免用户频繁登录。 用户可能遇到的难点包括跨域Cookie的设置、Token的传递方式、以及各个子系统之间的会话同步。需要分步骤说明如何配置sa-token,如何在前端uni-app中处理登录状态,以及后端如何验证Token。 可能还需要示例代码,比如后端的Controller处理登录和验证,前端uni-app的登录跳转和Token传递。例如,主系统登录后生成Token,重定向到子系统时携带Token参数,子系统后端向认证中心验证Token的有效性。 最后,要确保引用用户提供的参考内容,比如SaTokenEventCenter的使用,可能在事件监听时记录日志或执行其他操作。相关问题部分需要生成与实现方案相关的问题,比如如何处理跨域、安全性措施、Token刷新等。</think>### Java项目中集成sa-token与uni-app实现单点登录(SSO)方案 #### 1. 核心原理 单点登录(SSO)允许用户通过一次登录访问多个互信系统。基于sa-token的实现方案主要依赖以下机制: - **Token共享**:用户登录后生成全局Token,所有子系统通过验证该Token实现状态同步[^1]。 - **跨域Cookie/Header传递**:通过统一域名或跨域技术(如CORS)实现Token传递。 #### 2. 后端集成sa-token **步骤1:添加依赖** ```xml <dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-spring-boot-starter</artifactId> <version>1.34.0</version> </dependency> <dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-sso</artifactId> <version>1.34.0</version> </dependency> ``` **步骤2:配置SSO参数** ```java @Configuration public class SaTokenConfig { @Autowired private void configSaToken(SaTokenConfig config) { // 设置共享域名(需统一主域名) config.setCookieDomain(".example.com"); // 启用SSO模式 SaSsoManager.config() .setAuthUrl("/sso/auth") // 认证中心地址 .setCheckTicketUrl("/sso/checkTicket"); // Token校验地址 } } ``` **步骤3:实现认证中心接口** ```java @RestController public class SsoController { // 单点登录认证接口 @RequestMapping("/sso/auth") public Object ssoAuth(String redirectUrl) { if(StpUtil.isLogin()) { String token = StpUtil.getTokenValue(); return SaResult.ok().setData(token); } else { return SaResult.code(401).setMsg("未登录"); } } // Token校验接口 @RequestMapping("/sso/checkTicket") public SaResult checkTicket(String token) { return StpUtil.checkLogin(token) ? SaResult.ok() : SaResult.error("无效Token"); } } ``` #### 3. uni-app前端适配 **方案1:通过URL参数传递Token** ```javascript // 登录跳转逻辑 uni.request({ url: 'https://sso.example.com/login', success: (res) => { if(res.data.token) { uni.navigateTo({ url: '/subsystem?token=' + res.data.token }); } } }); ``` **方案2:跨域Cookie自动携带** ```javascript // 需要配置withCredentials uni.request({ url: 'https://api.example.com/checkLogin', withCredentials: true // 允许携带Cookie }); ``` #### 4. 安全性增强措施 - **HTTPS强制使用**:防止Token被截获 - **Token加密传输**:使用JWT格式携带签名 - **短期Token有效期**:通过refreshToken机制续期 ```java // 监听登录事件设置Token有效期[^1] SaTokenEventCenter.registerListener(new SaTokenListenerForSimple() { @Override public void doLogin(String loginType, Object loginId, SaLoginModel loginModel) { StpUtil.getTokenSession().setTimeout(30 * 60); // 30分钟有效期 } }); ``` #### 5. 完整流程示例 1. 用户访问uni-app子系统A 2. 跳转至SSO认证中心验证登录状态 3. 已登录则返回Token,否则进入登录页 4. 携带Token重定向回子系统A 5. 子系统A向认证中心验证Token有效性 6. 验证通过后建立局部会话
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值