开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
为了后续的产品社区,我们只需要建立一个登录服务即可将整个社区的登录全部管理,这个时候我们就需要用到单点登录,举个场景,假设我们的系统被切割为N个部分:商城、论坛、直播、社交…… 如果用户每访问一个模块都要登录一次,那么用户将会疯掉, 为了优化用户体验,我们急需一套机制将这N个系统的认证授权互通共享,让用户在一个系统登录之后,便可以畅通无阻的访问其它所有系统。
简而言之,单点登录可以做到:在多个互相信任的系统中,用户只需登录一次,就可以访问所有系统。
此时,我们就选择引入Sa-Token来实现单点登录
Sa-Token-SSO 由简入难划分为三种模式,解决不同架构下的 SSO 接入问题:
| 系统架构 | 采用模式 | 简介 |
|---|---|---|
| 前端同域 + 后端同 Redis | 模式一 | 共享 Cookie 同步会话 |
| 前端不同域 + 后端同 Redis | 模式二 | URL重定向传播会话 |
| 前端不同域 + 后端不同 Redis | 模式三 | Http请求获取会话 |
我们这里为了更好的增加扩展性和可用性,选择模式三
| **系统架构 ** | **采用模式 ** | **简介 ** |
|---|---|---|
| 前端同域 + 后端同 Redis | 模式一 | 共享 Cookie 同步会话 |
| 前端不同域 + 后端同 Redis | 模式二 | URL重定向传播会话 |
| 前端不同域 + 后端不同 Redis | 模式三 | Http请求获取会话 |
我们这里为了更好的增加扩展性和可用性,选择模式三
1.简介
Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证、权限认证、单点登录、OAuth2.0、分布式Session会话、微服务网关鉴权 等一系列权限相关问题。
2.引入依赖、添加配置文件
①引入Sa-Token
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.32.0</version>
</dependency>
②我们的项目是一个前后端分离微服务应用,所以我们不可采取单体架构(如单体内存来缓存token),故需要引入redis(或别的nosql)来实现中间件缓存,进行服务器间的token同步
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis-jackson</artifactId>
<version>1.32.0</version>
</dependency>
③redis连接池
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
④引入单点登录依赖
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-sso</artifactId>
<version>1.32.0</version>
</dependency>
<!-- Http请求工具(在模式三的单点注销功能下用到,如不需要可以注释掉) -->
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>forest-spring-boot-starter</artifactId>
<version>1.5.26</version>
</dependency>
⑤更改配置文件application.yml
# 端口
server:
port: 9000
# Sa-Token 配置
sa-token:
# ------- SSO-模式一相关配置 (非模式一不需要配置)
# cookie:
# 配置 Cookie 作用域
# domain: stp.com
# ------- SSO-模式二相关配置
sso:
# Ticket有效期 (单位: 秒),默认五分钟
ticket-timeout: 300
# 所有允许的授权回调地址
allow-url: "*"
# 是否打开单点注销功能
is-slo: true
# ------- SSO-模式三相关配置 (下面的配置在SSO模式三并且 is-slo=true 时打开)
# 是否打开模式三
isHttp: true
# 接口调用秘钥(用于SSO模式三的单点注销功能)
secretkey: kQwIOrYvnXmSDkwEiFngrKidMcdrgKor
# ---- 除了以上配置项,你还需要为 Sa-Token 配置http请求处理器(文档有步骤说明)
spring:
# Redis配置 (SSO模式一和模式二使用Redis来同步会话)
redis:
# Redis数据库索引(默认为0)
database: 1
# Redis服务器地址
host: 127.0.0.1
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码(默认为空)
password:
forest:
# 关闭 forest 请求日志打印
log-enabled: false
3.编写sso登录代码
@RestController
public class UserLoginController {
@RequestMapping("/sso/*")
public Object ssoRequest(){
return SaSsoProcessor.instance.serverDister();
}
@Autowired
private void configSso(SaSsoConfig sso) {
// 配置:未登录时返回的View
sso.setNotLoginView(() -> {
String msg = "当前会话在SSO-Server端尚未登录,请先访问"
+ "<a href='/sso/doLogin?name=sa&pwd=123456' target='_blank'> doLogin登录 </a>"
+ "进行登录之后,刷新页面开始授权";
return msg;
});
// 配置:登录处理函数
sso.setDoLoginHandle((name, pwd) -> {
// 此处仅做模拟登录,真实环境应该查询数据进行登录
if("sa".equals(name) && "123456".equals(pwd)) {
StpUtil.login(10001);
StpUtil.getSession().set("userId",10001);
return SaResult.ok("登录成功!").setData(StpUtil.getTokenValue());
}
return SaResult.error("登录失败!");
});
// 配置 Http 请求处理器 (在模式三的单点注销功能下用到,如不需要可以注释掉)
sso.setSendHttp(url -> {
try {
// 发起 http 请求
System.out.println("------ 发起请求:" + url);
return Forest.get(url).executeAsString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
});
}
}
此时小伙伴们是不是感觉不对劲,我们应该访问哪个接口去登陆呢?这是因为Sa-Token给我们封装了RestAPI,我们只需要直接调用http接口就可以了
登录接口:http://{host}:{port}/sso/doLogin
| 参数 | **是否必填 ** | **说明 ** |
|---|---|---|
| name | 是 | 用户名 |
| pwd | 是 | 密码 |
另外需要注意:此接口并非只能携带 name、pwd 参数,因为你可以在方法里通过 SaHolder.getRequest().getParam("xxx") 来获取前端提交的其它参数。
4.登录后session共享
我们可以在登录处理函数中进行设置session,从而在项目全局可以使用session中的用户信息
StpUtil.getSession().set("userId",user);
这里可以缓存基本数据类型或者是用户对象,获取的时候只需要转型一下即可
SysUser user = (SysUser) StpUtil.getSession().get("user");
String name = user.getName();
5.总结
这次分享就到这里了,Sa-Token还有好多好玩有意思的东西,大家可以自行去调研一下,国人的作品必须多多支持,也希望大家给点点关注,请作者喝杯咖啡熬夜写代码,感谢~