将SSO模式三的接口调用改为签名式校验

This commit is contained in:
click33
2022-04-29 03:23:46 +08:00
parent 5e3795e29e
commit de39d91b71
23 changed files with 575 additions and 281 deletions

View File

@@ -83,22 +83,33 @@ http://{host}:{port}/sso/checkTicket
http://{host}:{port}/sso/logout
```
接受参数:
| 参数 | 是否必填 | 说明 |
| :-------- | :-------- | :-------- |
| loginId | 否 | 要注销的账号id |
| secretkey | 否 | 接口通信秘钥 |
| back | 否 | 注销成功后的重定向地址 |
此接口有两种调用方式
##### 方式一:在 Client 的前端页面引导用户直接跳转,并带有 back 参数
例如:`http://{host}:{port}/sso/logout?back=xxx`代表用户注销成功后返回back地址
##### 4.1、方式一:在 Client 的前端页面引导用户直接跳转,并带有 back 参数
例如:
##### 方式二:在 Client 的后端通过 http 工具来调用
例如:`http://{host}:{port}/sso/logout?loginId={value}&secretkey={value}`,代表注销 账号=loginId 的账号返回json数据结果形如
``` url
http://{host}:{port}/sso/logout?back=xxx
```
用户注销成功后将返回 back 地址
##### 4.2、方式二:在 Client 的后端通过 http 工具来调用
接受参数:
| 参数 | 是否必填 | 说明 |
| :-------- | :-------- | :-------- |
| loginId | 是 | 要注销的账号 id |
| timestamp | 是 | 当前时间戳13位 |
| nonce | 是 | 随机字符串 |
| sign | 是 | 签名,生成算法:`md5( loginId={value}&nonce={value}&timestamp={value}&key={secretkey秘钥} )` |
例如:
``` url
http://{host}:{port}/sso/logout?loginId={value}&timestamp={value}&nonce={value}&sign={value}
```
将返回 json 数据结果,形如:
``` js
{
@@ -113,7 +124,7 @@ http://{host}:{port}/sso/logout
``` js
{
"code": 500, // 200表示请求成功非200标识请求失败
"msg": "无效秘钥xxx", // 失败原因
"msg": "签名无效xxx", // 失败原因
"data": null
}
```

View File

@@ -5,9 +5,11 @@
### 问在模式一与模式二中Client端 必须通过 Alone-Redis 插件来访问Redis吗
答:不必须,只是推荐,权限缓存与业务缓存分离后会减少 `SSO-Redis` 的访问压力,且可以避免多个 `Client端` 的缓存读写冲突
### 问:将旧有系统改造为单点登录时,应该注意哪些?
建议不要把其中一个系统改造为SSO服务端而是新起一个项目作为Server端所有旧有项目全部作为Client端与此对接
### 问SSO模式二第一个域名登录成功之后其他两个不会自动登录
系统1登录成功之后系统二与系统三需要点击登录按钮才会登录成功
@@ -15,13 +17,23 @@
> 第二个系统,需要:点击 [登录] 按钮 -> 登录成功 <br>
> 第三个系统,需要:点击 [登录] 按钮 -> 登录成功 (免去重复跳转登录页输入账号密码的步骤)
### 追问:那我是否可以设计成不需要点登录按钮的,只要访问页面,它就能登录成功
可以:加个过滤器检测到未登录 自动跳转就行了,详细可以参照章节:[[何时引导用户去登录]](/sso/sso-custom-login) 给出的建议进行设计
### 问我参照文档的SSO模式二搭建一直提示Ticket无效请问怎么回事
根据群友的反馈,出现此异常概率最大的原因是因为 `Client``Server` 没有连接同一个RedisSSO模式二中两者必须连接同一个 Redis 才可以登录成功,
如果您排查之后不是此原因可以加入QQ群或者在issues反馈一下
### 模式一或者模式二报错Could not write JSON: No serializer found for class com.pj.sso.SysUser and no properties discovered to create BeanSerializer
一般是因为在 sso-server 端往 session 上写入了某个实体类(比如 User而在 sso-client 端没有这个实体类,导致反序列化失败。
解决方案:在 sso-client 也新建上这个类,而且包名需要与 sso-server 端的一致(直接从 sso-server 把实体类复制过来就好了)
### 还有其它问题?
可以加群反馈一下,比较典型的问题我们解决之后都会提交到此页面方便大家快速排查

View File

@@ -93,14 +93,23 @@ public class SsoServerController {
// 配置 Http 请求处理器 (在模式三的单点注销功能下用到,如不需要可以注释掉)
cfg.sso.setSendHttp(url -> {
return OkHttps.sync(url).get().getBody().toString();
try {
// 发起 http 请求
System.out.println("发起请求:" + url);
return OkHttps.sync(url).get().getBody().toString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
});
}
}
```
注:在`setDoLoginHandle`函数里如果要获取name, pwd以外的参数可通过`SaHolder.getRequest().getParam("xxx")`来获取
- 在`setDoLoginHandle`函数里如果要获取name, pwd以外的参数可通过`SaHolder.getRequest().getParam("xxx")`来获取
- 在 `setSendHttp` 函数中,使用 `try-catch` 是为了提高整个注销流程的容错性,避免在一些极端情况下注销失败(例如:某个 Client 端上线之后又下线,导致 http 请求无法调用成功,从而阻断了整个注销流程)
全局异常处理:
``` java

View File

@@ -41,6 +41,7 @@ private void configSso(SaTokenConfig cfg) {
// 配置 Http 请求处理器
cfg.sso.setSendHttp(url -> {
System.out.println("发起请求:" + url);
return OkHttps.sync(url).get().getBody().toString();
});
}
@@ -70,12 +71,12 @@ sa-token:
``` java
// 自定义接口获取userinfo
@RequestMapping("/sso/userinfo")
public Object userinfo(String loginId, String secretkey) {
public Object userinfo(String loginId) {
System.out.println("---------------- 获取userinfo --------");
// 校验调用秘钥
SaSsoUtil.checkSecretkey(secretkey);
// 校验签名,防止敏感信息外泄
SaSsoUtil.checkSign(SaHolder.getRequest());
// 自定义返回结果(模拟)
return SaResult.ok()
.set("id", loginId)