gateway支持sso登录校验

This commit is contained in:
Github_lizhw 2025-01-09 23:55:27 +08:00
parent 78e810397b
commit 4e8b44352f
5 changed files with 192 additions and 1 deletions

View File

@ -66,6 +66,32 @@
<artifactId>ruoyi-common-satoken</artifactId>
</dependency>
<!-- Sa-Token 插件整合SSO -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-sso</artifactId>
<version>${satoken.version}</version>
</dependency>
<!-- Sa-Token 整合 jwt -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jwt</artifactId>
<version>${satoken.version}</version>
</dependency>
<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-redis-jackson</artifactId>
<version>${satoken.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- RuoYi Common Redis-->
<dependency>
<groupId>org.dromara</groupId>

View File

@ -32,7 +32,8 @@ public class AuthFilter {
return new SaReactorFilter()
// 拦截地址
.addInclude("/**")
.addExclude("/favicon.ico", "/actuator", "/actuator/**")
.addExclude("/actuator", "/actuator/**")
.addExclude("/favicon.ico", "/sso/getSsoAuthUrl", "/sso/isLogin", "/sso/doLoginByTicket")
// 鉴权方法每次访问进入
.setAuth(obj -> {
// 登录校验 -- 拦截所有路由

View File

@ -0,0 +1,122 @@
package org.dromara.gateway.sso;
import cn.dev33.satoken.sso.SaSsoManager;
import cn.dev33.satoken.sso.config.SaSsoClientConfig;
import cn.dev33.satoken.sso.model.SaCheckTicketResult;
import cn.dev33.satoken.sso.name.ParamName;
import cn.dev33.satoken.sso.processor.SaSsoClientProcessor;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaResult;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 前后台分离架构下集成SSO所需的代码 SSO-Client端TODO 后续用户相关接口通过rpc调用获取
*
* @author click33
*/
@RestController
public class SsoController {
// 当前是否登录
@RequestMapping("/sso/isLogin")
public Object isLogin() {
return SaResult.data(StpUtil.isLogin());
}
// 返回SSO认证中心登录地址
@RequestMapping("/sso/getSsoAuthUrl")
public SaResult getSsoAuthUrl(@RequestParam() String clientLoginUrl) {
String serverAuthUrl = buildServerAuthUrl(clientLoginUrl, "");
return SaResult.data(serverAuthUrl);
}
// ---------------------- 构建URL ----------------------
/**
* 构建URLServer端 单点登录地址支持vue页面的url构造
*
* @param clientLoginUrl Client端登录地址
* @param back 回调路径
* @return [SSO-Server端-认证地址 ]
*/
public String buildServerAuthUrl(String clientLoginUrl, String back) {
SaSsoClientConfig ssoConfig = SaSsoManager.getClientConfig();
ParamName paramName = SaSsoClientProcessor.instance.ssoClientTemplate.paramName;
// 服务端认证地址认证地址支持路由地址
String serverUrl = ssoConfig.splicingAuthUrl();
// 拼接客户端标识
String client = ssoConfig.getClient();
if (SaFoxUtil.isNotEmpty(client)) {
serverUrl = joinParam(serverUrl, paramName.client, client);
}
// 对back地址编码
back = (back == null ? "" : back);
back = SaFoxUtil.encodeUrl(back);
// 开始拼接 sso 统一认证地址形如serverAuthUrl = http://xxx.com?redirectUrl=xxx.com?back=xxx.com
/*
* 部分 Servlet 版本 request.getRequestURL() 返回的 url 带有 query 参数形如http://domain.com?id=1
* 如果不加判断会造成最终生成的 serverAuthUrl 带有双 back 参数 这个 if 判断正是为了解决此问题
*/
if (!clientLoginUrl.contains(paramName.back + "=" + back)) {
clientLoginUrl = joinParam(clientLoginUrl, paramName.back, back);
}
// 返回
return joinParam(serverUrl, paramName.redirect, clientLoginUrl);
}
/**
* 在url上拼接上kv参数并返回支持路由url 拼接
*
* @param url url
* @param key 参数名称
* @param value 参数值
* @return 拼接后的url字符串
*/
public static String joinParam(String url, String key, Object value) {
// 如果url或者key为空, 直接返回
if (!StringUtils.hasText(url) || !StringUtils.hasText(key)) {
return url;
}
String routerUrlSuffix = "";
int routerUrlIdx = url.indexOf("#/");
if (routerUrlIdx != -1) {
routerUrlSuffix = url.substring(routerUrlIdx);
url = url.substring(0, routerUrlIdx);
}
return SaFoxUtil.joinParam(url, key + "=" + value) + routerUrlSuffix;
}
// 根据ticket进行登录
@RequestMapping("/sso/doLoginByTicket")
public SaResult doLoginByTicket(@RequestParam() String ticket) {
SaCheckTicketResult ctr = SaSsoClientProcessor.instance.checkTicket(ticket, "/sso/doLoginByTicket");
StpUtil.login(ctr.loginId, ctr.remainSessionTimeout);
return SaResult.data(StpUtil.getTokenValue());
}
/*
* SSO-Client端处理所有SSO相关请求
* http://{host}:{port}/sso/login -- Client端登录地址接受参数back=登录后的跳转地址
* http://{host}:{port}/sso/logout -- Client端单点注销地址isSlo=true时打开接受参数back=注销后的跳转地址
* http://{host}:{port}/sso/logoutCall -- Client端单点注销回调地址isSlo=true时打开此接口为框架回调开发者无需关心
*/
@RequestMapping("/sso/*")
public Object ssoRequest() {
return SaSsoClientProcessor.instance.dister();
}
}

View File

@ -0,0 +1,18 @@
package org.dromara.gateway.sso;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/user/getUserInfo")
public SaResult getUserInfo() {
//TODO 后续改成统一从指定用户服务取用户应该通一接口
return SaResult.data(StpUtil.getTokenSession().get("loginUser"));
}
}

View File

@ -13,6 +13,30 @@ spring:
# 环境配置
active: @profiles.active@
# sa-token配置
sa-token:
sign:
# API client和server之间调用 接口签名秘钥 (随便乱摁几个字母即可)
secret-key: kQwIOrYbtXmSDkwEiFngrKidMcdrgKor
# token名称 (同时也是cookie名称)
token-name: Authorization
# 允许动态设置 token 有效期
dynamic-active-timeout: true
# 允许从 header 读取 token
is-read-header: true
# 关闭 cookie 鉴权 从根源杜绝 csrf 漏洞风险
is-read-cookie: false
# SSO-相关配置
sso-client:
# SSO-Server 端主机地址
server-url: http://sa-sso-server.com:19000
auth-url: http://localhost:9000/#/sso-login
client: "pc"
#jwt密钥
jwt-secret-key: abcdcosctlklmnopqrstuvwxyz
token-prefix: Bearer
--- # nacos 配置
spring:
cloud: