mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-09-18 17:48:03 +08:00
新增 getData 接口配置,在模式三拉取数据时可以传递任意参数
This commit is contained in:
@@ -4,6 +4,9 @@ import cn.dev33.satoken.error.SaErrorCode;
|
|||||||
import cn.dev33.satoken.exception.SaTokenException;
|
import cn.dev33.satoken.exception.SaTokenException;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request 包装类
|
* Request 包装类
|
||||||
* @author kong
|
* @author kong
|
||||||
@@ -70,8 +73,19 @@ public interface SaRequest {
|
|||||||
}
|
}
|
||||||
return paramValue;
|
return paramValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [请求体] 里提交的所有参数名称
|
||||||
|
* @return 参数名称列表
|
||||||
|
*/
|
||||||
|
public List<String> getParamNames();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [请求体] 里提交的所有参数
|
||||||
|
* @return 参数列表
|
||||||
|
*/
|
||||||
|
public Map<String, String> getParamMap();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在 [请求头] 里获取一个值
|
* 在 [请求头] 里获取一个值
|
||||||
* @param name 键
|
* @param name 键
|
||||||
|
@@ -262,12 +262,12 @@ public class SaTokenEventCenter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 全局组件载入
|
* 全局组件载入
|
||||||
* @param comtName 组件名称
|
* @param compName 组件名称
|
||||||
* @param comtObj 组件对象
|
* @param compObj 组件对象
|
||||||
*/
|
*/
|
||||||
public static void doRegisterComponent(String comtName, Object comtObj) {
|
public static void doRegisterComponent(String compName, Object compObj) {
|
||||||
for (SaTokenListener listener : listenerList) {
|
for (SaTokenListener listener : listenerList) {
|
||||||
listener.doRegisterComponent(comtName, comtObj);
|
listener.doRegisterComponent(compName, compObj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -103,10 +103,10 @@ public interface SaTokenListener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 全局组件载入
|
* 全局组件载入
|
||||||
* @param comtName 组件名称
|
* @param compName 组件名称
|
||||||
* @param comtObj 组件对象
|
* @param compObj 组件对象
|
||||||
*/
|
*/
|
||||||
public default void doRegisterComponent(String comtName, Object comtObj) {}
|
public default void doRegisterComponent(String compName, Object compObj) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* StpLogic 对象替换
|
* StpLogic 对象替换
|
||||||
|
@@ -106,13 +106,13 @@ public class SaTokenListenerForLog implements SaTokenListener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 全局组件载入
|
* 全局组件载入
|
||||||
* @param comtName 组件名称
|
* @param compName 组件名称
|
||||||
* @param comtObj 组件对象
|
* @param compObj 组件对象
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void doRegisterComponent(String comtName, Object comtObj) {
|
public void doRegisterComponent(String compName, Object compObj) {
|
||||||
String canonicalName = comtObj == null ? null : comtObj.getClass().getCanonicalName();
|
String canonicalName = compObj == null ? null : compObj.getClass().getCanonicalName();
|
||||||
log.info("全局组件 {} 载入成功: {}", comtName, canonicalName);
|
log.info("全局组件 {} 载入成功: {}", compName, canonicalName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,18 +1,18 @@
|
|||||||
package cn.dev33.satoken.sign;
|
package cn.dev33.satoken.sign;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
import cn.dev33.satoken.error.SaErrorCode;
|
import cn.dev33.satoken.error.SaErrorCode;
|
||||||
import cn.dev33.satoken.exception.SaTokenException;
|
import cn.dev33.satoken.exception.SaTokenException;
|
||||||
import cn.dev33.satoken.secure.SaSecureUtil;
|
import cn.dev33.satoken.secure.SaSecureUtil;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 参数签名算法
|
* 参数签名算法
|
||||||
*
|
*
|
||||||
* @author kong
|
* @author kong
|
||||||
* @since: 2022-4-27
|
* @since 2022-4-27
|
||||||
*/
|
*/
|
||||||
public interface SaSignTemplate {
|
public interface SaSignTemplate {
|
||||||
|
|
||||||
@@ -21,13 +21,13 @@ public interface SaSignTemplate {
|
|||||||
* @param paramsMap 参数列表
|
* @param paramsMap 参数列表
|
||||||
* @return 拼接出的参数字符串
|
* @return 拼接出的参数字符串
|
||||||
*/
|
*/
|
||||||
public default String joinParams(Map<String, Object> paramsMap) {
|
public default String joinParams(Map<String, ?> paramsMap) {
|
||||||
|
|
||||||
// 按照 k1=v1&k2=v2&k3=v3 排列
|
// 按照 k1=v1&k2=v2&k3=v3 排列
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (String key : paramsMap.keySet()) {
|
for (String key : paramsMap.keySet()) {
|
||||||
Object value = paramsMap.get(key);
|
Object value = paramsMap.get(key);
|
||||||
if(SaFoxUtil.isEmpty(value) == false) {
|
if( ! SaFoxUtil.isEmpty(value) ) {
|
||||||
sb.append(key).append("=").append(value).append("&");
|
sb.append(key).append("=").append(value).append("&");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,9 +46,9 @@ public interface SaSignTemplate {
|
|||||||
* @param paramsMap 参数列表
|
* @param paramsMap 参数列表
|
||||||
* @return 拼接出的参数字符串
|
* @return 拼接出的参数字符串
|
||||||
*/
|
*/
|
||||||
public default String joinParamsDictSort(Map<String, Object> paramsMap) {
|
public default String joinParamsDictSort(Map<String, ?> paramsMap) {
|
||||||
// 保证字段按照字典顺序排列
|
// 保证字段按照字典顺序排列
|
||||||
if(paramsMap instanceof TreeMap == false) {
|
if( ! (paramsMap instanceof TreeMap) ) {
|
||||||
paramsMap = new TreeMap<>(paramsMap);
|
paramsMap = new TreeMap<>(paramsMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,9 +62,17 @@ public interface SaSignTemplate {
|
|||||||
* @param key 秘钥
|
* @param key 秘钥
|
||||||
* @return 签名
|
* @return 签名
|
||||||
*/
|
*/
|
||||||
public default String createSign(Map<String, Object> paramsMap, String key) {
|
public default String createSign(Map<String, ?> paramsMap, String key) {
|
||||||
SaTokenException.throwByNull(key, "参与参数签名的秘钥不可为空", SaErrorCode.CODE_12201);
|
SaTokenException.throwByNull(key, "参与参数签名的秘钥不可为空", SaErrorCode.CODE_12201);
|
||||||
|
|
||||||
|
// 如果调用者不小心传入了 sign 参数,则此处需要将 sign 参数排除在外
|
||||||
|
// 为了保证不影响原有的 paramsMap,此处需要再复制一份
|
||||||
|
if(paramsMap.containsKey("sign")) {
|
||||||
|
paramsMap = new TreeMap<>(paramsMap);
|
||||||
|
paramsMap.remove("sign");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算签名
|
||||||
String paramsStr = joinParamsDictSort(paramsMap);
|
String paramsStr = joinParamsDictSort(paramsMap);
|
||||||
String fullStr = paramsStr + "&key=" + key;
|
String fullStr = paramsStr + "&key=" + key;
|
||||||
return SaSecureUtil.md5(fullStr);
|
return SaSecureUtil.md5(fullStr);
|
||||||
@@ -77,7 +85,7 @@ public interface SaSignTemplate {
|
|||||||
* @param sign 待验证的签名
|
* @param sign 待验证的签名
|
||||||
* @return 签名是否有效
|
* @return 签名是否有效
|
||||||
*/
|
*/
|
||||||
public default boolean isValidSign(Map<String, Object> paramsMap, String key, String sign) {
|
public default boolean isValidSign(Map<String, ?> paramsMap, String key, String sign) {
|
||||||
String theSign = createSign(paramsMap, key);
|
String theSign = createSign(paramsMap, key);
|
||||||
return theSign.equals(sign);
|
return theSign.equals(sign);
|
||||||
}
|
}
|
||||||
@@ -88,8 +96,8 @@ public interface SaSignTemplate {
|
|||||||
* @param key 秘钥
|
* @param key 秘钥
|
||||||
* @param sign 待验证的签名
|
* @param sign 待验证的签名
|
||||||
*/
|
*/
|
||||||
public default void checkSign(Map<String, Object> paramsMap, String key, String sign) {
|
public default void checkSign(Map<String, ?> paramsMap, String key, String sign) {
|
||||||
if(isValidSign(paramsMap, key, sign) == false) {
|
if( ! isValidSign(paramsMap, key, sign) ) {
|
||||||
throw new SaTokenException("无效签名:" + sign).setCode(SaErrorCode.CODE_12202);
|
throw new SaTokenException("无效签名:" + sign).setCode(SaErrorCode.CODE_12202);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,15 +119,15 @@ public interface SaSignTemplate {
|
|||||||
* 给 paramsMap 追加 timestamp、nonce、sign 三个参数,并转换为参数字符串,形如:
|
* 给 paramsMap 追加 timestamp、nonce、sign 三个参数,并转换为参数字符串,形如:
|
||||||
* <code>data=xxx8nonce=xxx8timestamp=xxx8sign=xxx</code>
|
* <code>data=xxx8nonce=xxx8timestamp=xxx8sign=xxx</code>
|
||||||
* @param paramsMap 参数列表
|
* @param paramsMap 参数列表
|
||||||
* @param key 秘钥
|
* @param key 秘钥
|
||||||
* @return 加工后的参数列表 转化为的参数字符串
|
* @return 加工后的参数列表 转化为的参数字符串
|
||||||
*/
|
*/
|
||||||
public default String addSignParamsToString(Map<String, Object> paramsMap, String key) {
|
public default String addSignParamsAndToString(Map<String, Object> paramsMap, String key) {
|
||||||
// 追加参数
|
// 追加参数
|
||||||
paramsMap = addSignParams(paramsMap, key);
|
paramsMap = addSignParams(paramsMap, key);
|
||||||
|
|
||||||
// .
|
// .
|
||||||
return joinParams(paramsMap);
|
return joinParams(paramsMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -139,9 +147,26 @@ public interface SaSignTemplate {
|
|||||||
* @param allowDisparity 允许的最大时间差(单位:ms),-1 代表不限制
|
* @param allowDisparity 允许的最大时间差(单位:ms),-1 代表不限制
|
||||||
*/
|
*/
|
||||||
public default void checkTimestamp(long timestamp, long allowDisparity) {
|
public default void checkTimestamp(long timestamp, long allowDisparity) {
|
||||||
if(isValidTimestamp(timestamp, allowDisparity) == false) {
|
if( ! isValidTimestamp(timestamp, allowDisparity) ) {
|
||||||
throw new SaTokenException("timestamp 超出允许的范围:" + timestamp).setCode(SaErrorCode.CODE_12203);
|
throw new SaTokenException("timestamp 超出允许的范围:" + timestamp).setCode(SaErrorCode.CODE_12203);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------ 以下为兼容旧版本的方法 ------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请更换为 addSignParamsAndToString
|
||||||
|
* @param paramsMap 参数列表
|
||||||
|
* @param key 秘钥
|
||||||
|
* @return 加工后的参数列表 转化为的参数字符串
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public default String addSignParamsToString(Map<String, Object> paramsMap, String key) {
|
||||||
|
// 追加参数
|
||||||
|
paramsMap = addSignParams(paramsMap, key);
|
||||||
|
|
||||||
|
// .
|
||||||
|
return joinParams(paramsMap);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,17 +1,17 @@
|
|||||||
package com.pj.sso;
|
package com.pj.sso;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.config.SaSsoConfig;
|
||||||
|
import cn.dev33.satoken.context.SaHolder;
|
||||||
|
import cn.dev33.satoken.sso.SaSsoProcessor;
|
||||||
|
import cn.dev33.satoken.sso.SaSsoUtil;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.dev33.satoken.util.SaResult;
|
||||||
|
import com.dtflys.forest.Forest;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
import com.dtflys.forest.Forest;
|
|
||||||
|
|
||||||
import cn.dev33.satoken.config.SaSsoConfig;
|
|
||||||
import cn.dev33.satoken.sso.SaSsoProcessor;
|
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
|
||||||
import cn.dev33.satoken.util.SaResult;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sa-Token-SSO Server端 Controller
|
* Sa-Token-SSO Server端 Controller
|
||||||
* @author kong
|
* @author kong
|
||||||
@@ -63,5 +63,23 @@ public class SsoServerController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 示例:获取数据接口(用于在模式三下,为 client 端开放拉取数据的接口)
|
||||||
|
@RequestMapping("/sso/getData")
|
||||||
|
public Object userinfo(String apiType, String loginId) {
|
||||||
|
System.out.println("---------------- 获取数据 ----------------");
|
||||||
|
System.out.println("apiType=" + apiType);
|
||||||
|
System.out.println("loginId=" + loginId);
|
||||||
|
|
||||||
|
// 校验签名:只有拥有正确秘钥发起的请求才能通过校验
|
||||||
|
SaSsoUtil.checkSign(SaHolder.getRequest());
|
||||||
|
|
||||||
|
// 自定义返回结果(模拟)
|
||||||
|
return SaResult.ok()
|
||||||
|
.set("id", loginId)
|
||||||
|
.set("name", "LinXiaoYu")
|
||||||
|
.set("sex", "女")
|
||||||
|
.set("age", 18);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
package com.pj.sso;
|
package com.pj.sso;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.context.SaHolder;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@@ -13,6 +14,10 @@ import cn.dev33.satoken.sso.SaSsoUtil;
|
|||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
import cn.dev33.satoken.util.SaResult;
|
import cn.dev33.satoken.util.SaResult;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sa-Token-SSO Client端 Controller
|
* Sa-Token-SSO Client端 Controller
|
||||||
* @author kong
|
* @author kong
|
||||||
@@ -52,11 +57,17 @@ public class SsoClientController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 查询我的账号信息
|
// 查询我的账号信息
|
||||||
@RequestMapping("/sso/myinfo")
|
@RequestMapping("/sso/myInfo")
|
||||||
public Object myinfo() {
|
public Object myInfo() {
|
||||||
Object userinfo = SaSsoUtil.getUserinfo(StpUtil.getLoginId());
|
// 组织请求参数
|
||||||
System.out.println("--------info:" + userinfo);
|
Map<String, Object> map = new HashMap<>();
|
||||||
return userinfo;
|
map.put("apiType", "userinfo");
|
||||||
|
map.put("loginId", StpUtil.getLoginId());
|
||||||
|
|
||||||
|
// 发起请求
|
||||||
|
Object resData = SaSsoUtil.getData("/sso/getData", map);
|
||||||
|
System.out.println("sso-server 返回的信息:" + resData);
|
||||||
|
return resData;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 全局异常拦截
|
// 全局异常拦截
|
||||||
|
@@ -18,9 +18,9 @@ sa-token:
|
|||||||
slo-url: http://sa-sso-server.com:9000/sso/signout
|
slo-url: http://sa-sso-server.com:9000/sso/signout
|
||||||
# 接口调用秘钥
|
# 接口调用秘钥
|
||||||
secretkey: kQwIOrYvnXmSDkwEiFngrKidMcdrgKor
|
secretkey: kQwIOrYvnXmSDkwEiFngrKidMcdrgKor
|
||||||
# SSO-Server端 查询userinfo地址
|
# 查询数据地址
|
||||||
userinfo-url: http://sa-sso-server.com:9000/sso/userinfo
|
get-data-url: http://sa-sso-server.com:9000/sso/getData
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
# 配置 Redis 连接 (此处与SSO-Server端连接不同的Redis)
|
# 配置 Redis 连接 (此处与SSO-Server端连接不同的Redis)
|
||||||
redis:
|
redis:
|
||||||
|
@@ -98,109 +98,160 @@ forest.log-enabled: false
|
|||||||
> 注:如果已测试运行模式二,可先将Redis中的数据清空,以防旧数据对测试造成干扰
|
> 注:如果已测试运行模式二,可先将Redis中的数据清空,以防旧数据对测试造成干扰
|
||||||
|
|
||||||
|
|
||||||
### 3、获取 Userinfo
|
### 3、获取 UserInfo
|
||||||
除了账号id,我们可能还需要将用户的昵称、头像等信息从 Server端 带到 Client端,即:用户资料的同步。
|
除了账号id,我们可能还需要将用户的昵称、头像等信息从 Server端 带到 Client端,即:用户资料的拉取。
|
||||||
|
|
||||||
在模式二中我们只需要将需要同步的资料放到 SaSession 即可,但是在模式三中两端不再连接同一个Redis,这时候我们需要通过http接口来同步信息:
|
在模式二中我们只需要将需要同步的资料放到 SaSession 即可,但是在模式三中两端不再连接同一个 Redis,这时候我们需要通过 http 接口来同步信息。
|
||||||
|
|
||||||
|
在旧版本`(<= v1.34.0)` 框架提供的方案是配置 getUserinfo 接口地址,从 client 调用拉取数据,该方案有以下缺点:
|
||||||
|
- 每次调用只能传递固定 loginId 一个参数,不方便。
|
||||||
|
- 只能拉取 userinfo 数据,不通用。
|
||||||
|
- 如果还需要拉取其它业务数据,需要再自定义一个接口,比较麻烦。
|
||||||
|
|
||||||
|
为此,我们设计了更通用、灵活的 getData 接口,解决上述三个难题。
|
||||||
|
|
||||||
|
#### 3.1、首先在 Server 端开放一个查询数据的接口
|
||||||
|
|
||||||
#### 3.1、在 Server 端自定义接口,查询用户资料
|
|
||||||
``` java
|
``` java
|
||||||
// 自定义接口:获取userinfo
|
// 示例:获取数据接口(用于在模式三下,为 client 端开放拉取数据的接口)
|
||||||
@RequestMapping("/sso/userinfo")
|
@RequestMapping("/sso/getData")
|
||||||
public Object userinfo(String loginId) {
|
public Object userinfo(String apiType, String loginId) {
|
||||||
System.out.println("---------------- 获取userinfo --------");
|
System.out.println("---------------- 获取数据 ----------------");
|
||||||
|
System.out.println("apiType=" + apiType);
|
||||||
// 校验签名,防止敏感信息外泄
|
System.out.println("loginId=" + loginId);
|
||||||
|
|
||||||
|
// 校验签名:只有拥有正确秘钥发起的请求才能通过校验
|
||||||
SaSsoUtil.checkSign(SaHolder.getRequest());
|
SaSsoUtil.checkSign(SaHolder.getRequest());
|
||||||
|
|
||||||
// 自定义返回结果(模拟)
|
// 自定义返回结果(模拟)
|
||||||
return SaResult.ok()
|
return SaResult.ok()
|
||||||
.set("id", loginId)
|
.set("id", loginId)
|
||||||
.set("name", "linxiaoyu")
|
.set("name", "LinXiaoYu")
|
||||||
.set("sex", "女")
|
.set("sex", "女")
|
||||||
.set("age", 18);
|
.set("age", 18);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 3.2、在 Client 端调用此接口查询 userinfo
|
#### 3.2、在 Client 端调用此接口查询数据
|
||||||
|
|
||||||
首先在 application.yml 中配置接口地址:
|
首先在 application.yml 中配置接口地址:
|
||||||
<!---------------------------- tabs:start ---------------------------->
|
<!---------------------------- tabs:start ---------------------------->
|
||||||
<!------------- tab:yaml 风格 ------------->
|
<!------------- tab:yaml 风格 ------------->
|
||||||
``` yaml
|
``` yaml
|
||||||
sa-token:
|
sa-token:
|
||||||
sso:
|
sso:
|
||||||
# SSO-Server端 查询userinfo地址
|
# sso-server 端拉取数据地址
|
||||||
userinfo-url: http://sa-sso-server.com:9000/sso/userinfo
|
get-data-url: http://sa-sso-server.com:9000/sso/getData
|
||||||
```
|
```
|
||||||
<!------------- tab:properties 风格 ------------->
|
<!------------- tab:properties 风格 ------------->
|
||||||
``` properties
|
``` properties
|
||||||
# SSO-Server端 查询userinfo地址
|
# sso-server 端拉取数据地址
|
||||||
sa-token.sso.userinfo-url=http://sa-sso-server.com:9000/sso/userinfo
|
sa-token.sso.get-data-url=http://sa-sso-server.com:9000/sso/getData
|
||||||
```
|
```
|
||||||
<!---------------------------- tabs:end ---------------------------->
|
<!---------------------------- tabs:end ---------------------------->
|
||||||
|
|
||||||
|
然后在 `SsoClientController` 中新增接口
|
||||||
|
|
||||||
然后在`SsoClientController`中新增接口
|
|
||||||
``` java
|
``` java
|
||||||
// 查询我的账号信息
|
// 查询我的账号信息
|
||||||
@RequestMapping("/sso/myinfo")
|
@RequestMapping("/sso/myInfo")
|
||||||
public Object myinfo() {
|
public Object myInfo() {
|
||||||
Object userinfo = SaSsoUtil.getUserinfo(StpUtil.getLoginId());
|
// 组织请求参数
|
||||||
System.out.println("--------info:" + userinfo);
|
Map<String, Object> map = new HashMap<>();
|
||||||
return userinfo;
|
map.put("apiType", "userinfo");
|
||||||
|
map.put("loginId", StpUtil.getLoginId());
|
||||||
|
|
||||||
|
// 发起请求
|
||||||
|
Object resData = SaSsoUtil.getData(map);
|
||||||
|
System.out.println("sso-server 返回的信息:" + resData);
|
||||||
|
return resData;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 3.3、访问测试
|
#### 3.3、访问测试
|
||||||
访问测试:[http://sa-sso-client1.com:9001/sso/myinfo](http://sa-sso-client1.com:9001/sso/myinfo)
|
访问测试:[http://sa-sso-client1.com:9001/sso/myInfo](http://sa-sso-client1.com:9001/sso/myInfo)
|
||||||
|
|
||||||
|
|
||||||
### 4、自定义接口通信
|
### 4、自定义接口通信
|
||||||
|
|
||||||
群里有小伙伴提问:`SaSsoUtil.getUserinfo` 提供的参数太少,只有一个 loginId,无法满足业务需求怎么办?
|
上述示例展示在 client 端向 server 拉取 userinfo 数据的步骤,如果你还需要拉取其它业务的数据,稍加改造示例便可以实现。
|
||||||
|
|
||||||
答:SaSsoUtil.getUserinfo只是为了避免你在项目中硬编码认证中心 url 而提供的简易封装,如果这个API无法满足你的业务需求,
|
#### 4.1、方式一,使用 apiType 参数来区分业务
|
||||||
你完全可以在 Server 端自定义一些接口然后从 Client 端使用 http 工具调用即可。
|
|
||||||
|
|
||||||
以下是一个简单的示例:
|
我们可以约定好,使用 apiType 来区分不同的业务,例如:
|
||||||
|
- 当 `apiType=userinfo` 时:代表拉取用户资料。
|
||||||
|
- 当 `apiType=followList` 时:代表拉取用户的关注列表。
|
||||||
|
- 当 `apiType=fansList` 时:代表拉取用户的粉丝列表。
|
||||||
|
|
||||||
#### 4.1、先在 sso-server 端自定义一个接口
|
此时,我们便可以通过在 client 端传入不同的 apiType 参数,来区分不同的业务。
|
||||||
``` java
|
|
||||||
// 获取指定用户的关注列表
|
|
||||||
@RequestMapping("/sso/getFollowList")
|
|
||||||
public Object ssoRequest(Long loginId) {
|
|
||||||
|
|
||||||
// 校验签名,签名不通过直接抛出异常
|
|
||||||
SaSsoUtil.checkSign(SaHolder.getRequest());
|
|
||||||
|
|
||||||
// 查询数据 (此处仅做模拟)
|
|
||||||
List<Integer> list = Arrays.asList(10041, 10042, 10043, 10044);
|
|
||||||
|
|
||||||
// 返回
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### 4.2、然后在 sso-client 端调用这个接口
|
|
||||||
``` java
|
``` java
|
||||||
// 查询我的账号信息
|
// 查询我的账号信息
|
||||||
@RequestMapping("/sso/myFollowList")
|
@RequestMapping("/sso/myFollowList")
|
||||||
public Object myFollowList() {
|
public Object myFollowList() {
|
||||||
// 组织url,加上签名参数
|
// 组织请求参数
|
||||||
String url = SaSsoUtil.addSignParams("http://sa-sso-server.com:9000/sso/getFollowList", StpUtil.getLoginId());
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
map.put("apiType", "followList"); // 关键代码,代表本次我要拉取关注列表
|
||||||
// 调用,并返回 SaResult 结果
|
map.put("loginId", StpUtil.getLoginId());
|
||||||
SaResult res = SaSsoUtil.request(url);
|
|
||||||
|
// 发起请求
|
||||||
// 返回给前端
|
Object resData = SaSsoUtil.getData(map);
|
||||||
return res;
|
System.out.println("sso-server 返回的信息:" + resData);
|
||||||
|
return resData;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
然后在 server 端我们通过不同的 apiType 值,返回不同的信息即可。
|
||||||
|
|
||||||
|
|
||||||
|
#### 4.2、方式二:直接在调用接口时传入一个自定义 path
|
||||||
|
|
||||||
|
我们可以 client 端,调用 `SaSsoUtil.getData` 方法时,传入一个自定义 path,例如:
|
||||||
|
|
||||||
|
``` java
|
||||||
|
// 查询我的账号信息
|
||||||
|
@RequestMapping("/sso/myFansList")
|
||||||
|
public Object myFansList() {
|
||||||
|
// 组织请求参数
|
||||||
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
// map.put("apiType", "userinfo"); // 此时已经不需要 apiType 参数了
|
||||||
|
map.put("loginId", StpUtil.getLoginId());
|
||||||
|
|
||||||
|
// 发起请求 (传入自定义的 path 地址)
|
||||||
|
Object resData = SaSsoUtil.getData("/sso/getFansList", map);
|
||||||
|
System.out.println("sso-server 返回的信息:" + resData);
|
||||||
|
return resData;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
同时,我们需要在 server 端开放这个自定义的 `/sso/getFansList` 接口:
|
||||||
|
|
||||||
|
``` java
|
||||||
|
// 获取指定用户的粉丝列表
|
||||||
|
@RequestMapping("/sso/getFansList")
|
||||||
|
public Object getFansList(Long loginId) {
|
||||||
|
System.out.println("---------------- 获取 loginId=" + loginId + " 的粉丝列表 ----------------");
|
||||||
|
|
||||||
|
// 校验签名:只有拥有正确秘钥发起的请求才能通过校验
|
||||||
|
SaSsoUtil.checkSign(SaHolder.getRequest());
|
||||||
|
|
||||||
|
// 查询数据 (此处仅做模拟)
|
||||||
|
List<Integer> list = Arrays.asList(10041, 10042, 10043, 10044);
|
||||||
|
|
||||||
|
// 返回
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**注意:使用此方案时,需要在 client 端配置 `sa-token.sso.server-url` 地址,例如:**
|
||||||
|
``` yaml
|
||||||
|
sa-token:
|
||||||
|
sso:
|
||||||
|
# sso-server 端主机地址
|
||||||
|
server-url: http://sa-sso-server.com:9000
|
||||||
|
```
|
||||||
|
|
||||||
#### 4.3、访问测试
|
#### 4.3、访问测试
|
||||||
访问测试:[http://sa-sso-client1.com:9001/sso/myFollowList](http://sa-sso-client1.com:9001/sso/myFollowList)
|
访问测试:[http://sa-sso-client1.com:9001/sso/myFansList](http://sa-sso-client1.com:9001/sso/myFansList)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -4,6 +4,9 @@ import org.apache.dubbo.rpc.RpcContext;
|
|||||||
|
|
||||||
import cn.dev33.satoken.context.model.SaRequest;
|
import cn.dev33.satoken.context.model.SaRequest;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request for Dubbo
|
* Request for Dubbo
|
||||||
*
|
*
|
||||||
@@ -42,6 +45,24 @@ public class SaRequestForDubbo implements SaRequest {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [请求体] 里提交的所有参数名称
|
||||||
|
* @return 参数名称列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<String> getParamNames(){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [请求体] 里提交的所有参数
|
||||||
|
* @return 参数列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getParamMap(){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在 [请求头] 里获取一个值
|
* 在 [请求头] 里获取一个值
|
||||||
*/
|
*/
|
||||||
|
@@ -3,6 +3,9 @@ package cn.dev33.satoken.context.dubbo3.model;
|
|||||||
import cn.dev33.satoken.context.model.SaRequest;
|
import cn.dev33.satoken.context.model.SaRequest;
|
||||||
import org.apache.dubbo.rpc.RpcContext;
|
import org.apache.dubbo.rpc.RpcContext;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request for Dubbo3
|
* Request for Dubbo3
|
||||||
*
|
*
|
||||||
@@ -41,6 +44,24 @@ public class SaRequestForDubbo3 implements SaRequest {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [请求体] 里提交的所有参数名称
|
||||||
|
* @return 参数名称列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<String> getParamNames(){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [请求体] 里提交的所有参数
|
||||||
|
* @return 参数列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getParamMap(){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在 [请求头] 里获取一个值
|
* 在 [请求头] 里获取一个值
|
||||||
*/
|
*/
|
||||||
|
@@ -3,6 +3,9 @@ package cn.dev33.satoken.context.grpc.model;
|
|||||||
import cn.dev33.satoken.context.grpc.context.SaTokenGrpcContext;
|
import cn.dev33.satoken.context.grpc.context.SaTokenGrpcContext;
|
||||||
import cn.dev33.satoken.context.model.SaRequest;
|
import cn.dev33.satoken.context.model.SaRequest;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request for grpc
|
* Request for grpc
|
||||||
*
|
*
|
||||||
@@ -27,6 +30,24 @@ public class SaRequestForGrpc implements SaRequest {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [请求体] 里提交的所有参数名称
|
||||||
|
* @return 参数名称列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<String> getParamNames(){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [请求体] 里提交的所有参数
|
||||||
|
* @return 参数列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getParamMap(){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在 [请求头] 里获取一个值
|
* 在 [请求头] 里获取一个值
|
||||||
*/
|
*/
|
||||||
|
@@ -61,31 +61,36 @@ public class SaSsoConfig implements Serializable {
|
|||||||
*/
|
*/
|
||||||
public String authUrl = "/sso/auth";
|
public String authUrl = "/sso/auth";
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 是否打开单点注销功能
|
// * 是否打开单点注销功能
|
||||||
*/
|
// */
|
||||||
// public Boolean isSlo = true; // 同Server端
|
// public Boolean isSlo = true; // 同Server端,不再重复声明
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 是否打开模式三(此值为 true 时将使用 http 请求:校验ticket值、单点注销、获取userinfo)
|
// * 是否打开模式三(此值为 true 时将使用 http 请求:校验ticket值、单点注销、获取userinfo)
|
||||||
*/
|
// */
|
||||||
// public Boolean isHttp = false; // 同Server端
|
// public Boolean isHttp = false; // 同Server端,不再重复声明
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 接口调用秘钥 (用于SSO模式三单点注销的接口通信身份校验)
|
// * 接口调用秘钥 (用于SSO模式三单点注销的接口通信身份校验)
|
||||||
*/
|
// */
|
||||||
// public String secretkey; // 同Server端
|
// public String secretkey; // 同Server端,不再重复声明
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置 Server 端的 ticket 校验地址
|
* 配置 Server 端的 ticket 校验地址
|
||||||
*/
|
*/
|
||||||
public String checkTicketUrl = "/sso/checkTicket";
|
public String checkTicketUrl = "/sso/checkTicket";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置 Server 端查询数据 getData 地址
|
||||||
|
*/
|
||||||
|
public String getDataUrl = "/sso/getData";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置 Server 端查询 userinfo 地址
|
* 配置 Server 端查询 userinfo 地址
|
||||||
*/
|
*/
|
||||||
public String userinfoUrl = "/sso/userinfo";
|
public String userinfoUrl = "/sso/userinfo";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置 Server 端单点注销地址
|
* 配置 Server 端单点注销地址
|
||||||
*/
|
*/
|
||||||
@@ -97,7 +102,7 @@ public class SaSsoConfig implements Serializable {
|
|||||||
public String ssoLogoutCall;
|
public String ssoLogoutCall;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置 Server 端主机总地址,拼接在 authUrl、checkTicketUrl、userinfoUrl、sloUrl 属性前面,用以简化各种 url 配置
|
* 配置 Server 端主机总地址,拼接在 authUrl、checkTicketUrl、getDataUrl、sloUrl 属性前面,用以简化各种 url 配置
|
||||||
*/
|
*/
|
||||||
public String serverUrl;
|
public String serverUrl;
|
||||||
|
|
||||||
@@ -240,6 +245,22 @@ public class SaSsoConfig implements Serializable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Server 端查询数据 getData 地址
|
||||||
|
*/
|
||||||
|
public String getGetDataUrl() {
|
||||||
|
return getDataUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param getDataUrl 配置 Server 端查询数据 getData 地址
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public SaSsoConfig setGetDataUrl(String getDataUrl) {
|
||||||
|
this.getDataUrl = getDataUrl;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 配置的 Server 端查询 userinfo 地址
|
* @return 配置的 Server 端查询 userinfo 地址
|
||||||
*/
|
*/
|
||||||
@@ -289,14 +310,14 @@ public class SaSsoConfig implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 配置的 Server 端主机总地址,拼接在 authUrl、checkTicketUrl、userinfoUrl、sloUrl 属性前面,用以简化各种 url 配置
|
* @return 配置的 Server 端主机总地址,拼接在 authUrl、checkTicketUrl、getDataUrl、sloUrl 属性前面,用以简化各种 url 配置
|
||||||
*/
|
*/
|
||||||
public String getServerUrl() {
|
public String getServerUrl() {
|
||||||
return serverUrl;
|
return serverUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param serverUrl 配置 Server 端主机总地址,拼接在 authUrl、checkTicketUrl、userinfoUrl、sloUrl 属性前面,用以简化各种 url 配置
|
* @param serverUrl 配置 Server 端主机总地址,拼接在 authUrl、checkTicketUrl、getDataUrl、sloUrl 属性前面,用以简化各种 url 配置
|
||||||
* @return 对象自身
|
* @return 对象自身
|
||||||
*/
|
*/
|
||||||
public SaSsoConfig setServerUrl(String serverUrl) {
|
public SaSsoConfig setServerUrl(String serverUrl) {
|
||||||
@@ -331,6 +352,7 @@ public class SaSsoConfig implements Serializable {
|
|||||||
+ ", client=" + client
|
+ ", client=" + client
|
||||||
+ ", authUrl=" + authUrl
|
+ ", authUrl=" + authUrl
|
||||||
+ ", checkTicketUrl=" + checkTicketUrl
|
+ ", checkTicketUrl=" + checkTicketUrl
|
||||||
|
+ ", getDataUrl=" + getDataUrl
|
||||||
+ ", userinfoUrl=" + userinfoUrl
|
+ ", userinfoUrl=" + userinfoUrl
|
||||||
+ ", sloUrl=" + sloUrl
|
+ ", sloUrl=" + sloUrl
|
||||||
+ ", ssoLogoutCall=" + ssoLogoutCall
|
+ ", ssoLogoutCall=" + ssoLogoutCall
|
||||||
@@ -356,6 +378,13 @@ public class SaSsoConfig implements Serializable {
|
|||||||
return SaFoxUtil.spliceTwoUrl(getServerUrl(), getCheckTicketUrl());
|
return SaFoxUtil.spliceTwoUrl(getServerUrl(), getCheckTicketUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 获取拼接url:Server 端查询数据 getData 地址
|
||||||
|
*/
|
||||||
|
public String splicingGetDataUrl() {
|
||||||
|
return SaFoxUtil.spliceTwoUrl(getServerUrl(), getGetDataUrl());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 获取拼接url:Server 端查询 userinfo 地址
|
* @return 获取拼接url:Server 端查询 userinfo 地址
|
||||||
*/
|
*/
|
||||||
|
@@ -1,12 +1,5 @@
|
|||||||
package cn.dev33.satoken.sso;
|
package cn.dev33.satoken.sso;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
import cn.dev33.satoken.SaManager;
|
import cn.dev33.satoken.SaManager;
|
||||||
import cn.dev33.satoken.config.SaSsoConfig;
|
import cn.dev33.satoken.config.SaSsoConfig;
|
||||||
import cn.dev33.satoken.context.model.SaRequest;
|
import cn.dev33.satoken.context.model.SaRequest;
|
||||||
@@ -21,6 +14,8 @@ import cn.dev33.satoken.strategy.SaStrategy;
|
|||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
import cn.dev33.satoken.util.SaResult;
|
import cn.dev33.satoken.util.SaResult;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sa-Token-SSO 单点登录模块
|
* Sa-Token-SSO 单点登录模块
|
||||||
* @author kong
|
* @author kong
|
||||||
@@ -153,7 +148,7 @@ public class SaSsoTemplate {
|
|||||||
}
|
}
|
||||||
String loginId = SaManager.getSaTokenDao().get(splicingTicketSaveKey(ticket));
|
String loginId = SaManager.getSaTokenDao().get(splicingTicketSaveKey(ticket));
|
||||||
// 如果是 "a,b" 的格式,则只取最前面的一项
|
// 如果是 "a,b" 的格式,则只取最前面的一项
|
||||||
if(loginId != null && loginId.indexOf(",") > -1) {
|
if(loginId != null && loginId.contains(",")) {
|
||||||
String[] arr = loginId.split(",");
|
String[] arr = loginId.split(",");
|
||||||
loginId = arr[0];
|
loginId = arr[0];
|
||||||
}
|
}
|
||||||
@@ -206,7 +201,7 @@ public class SaSsoTemplate {
|
|||||||
|
|
||||||
// 如果是 "a,b" 的格式,则解析出对应的 Client
|
// 如果是 "a,b" 的格式,则解析出对应的 Client
|
||||||
String ticketClient = null;
|
String ticketClient = null;
|
||||||
if(loginId.indexOf(",") > -1) {
|
if(loginId.contains(",")) {
|
||||||
String[] arr = loginId.split(",");
|
String[] arr = loginId.split(",");
|
||||||
loginId = arr[0];
|
loginId = arr[0];
|
||||||
ticketClient = arr[1];
|
ticketClient = arr[1];
|
||||||
@@ -252,7 +247,7 @@ public class SaSsoTemplate {
|
|||||||
public void checkRedirectUrl(String url) {
|
public void checkRedirectUrl(String url) {
|
||||||
|
|
||||||
// 1、是否是一个有效的url
|
// 1、是否是一个有效的url
|
||||||
if(SaFoxUtil.isUrl(url) == false) {
|
if( ! SaFoxUtil.isUrl(url) ) {
|
||||||
throw new SaSsoException("无效redirect:" + url).setCode(SaSsoErrorCode.CODE_30001);
|
throw new SaSsoException("无效redirect:" + url).setCode(SaSsoErrorCode.CODE_30001);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,12 +259,11 @@ public class SaSsoTemplate {
|
|||||||
|
|
||||||
// 3、是否在[允许地址列表]之中
|
// 3、是否在[允许地址列表]之中
|
||||||
List<String> authUrlList = Arrays.asList(getAllowUrl().replaceAll(" ", "").split(","));
|
List<String> authUrlList = Arrays.asList(getAllowUrl().replaceAll(" ", "").split(","));
|
||||||
if(SaStrategy.me.hasElement.apply(authUrlList, url) == false) {
|
if( ! SaStrategy.me.hasElement.apply(authUrlList, url) ) {
|
||||||
throw new SaSsoException("非法redirect:" + url).setCode(SaSsoErrorCode.CODE_30002);
|
throw new SaSsoException("非法redirect:" + url).setCode(SaSsoErrorCode.CODE_30002);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 校验通过 √
|
// 校验通过 √
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -285,7 +279,7 @@ public class SaSsoTemplate {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SaSession session = getStpLogic().getSessionByLoginId(loginId);
|
SaSession session = getStpLogic().getSessionByLoginId(loginId);
|
||||||
Set<String> urlSet = session.get(SaSsoConsts.SLO_CALLBACK_SET_KEY, ()-> new HashSet<String>());
|
Set<String> urlSet = session.get(SaSsoConsts.SLO_CALLBACK_SET_KEY, HashSet::new);
|
||||||
urlSet.add(sloCallbackUrl);
|
urlSet.add(sloCallbackUrl);
|
||||||
session.set(SaSsoConsts.SLO_CALLBACK_SET_KEY, urlSet);
|
session.set(SaSsoConsts.SLO_CALLBACK_SET_KEY, urlSet);
|
||||||
}
|
}
|
||||||
@@ -304,7 +298,7 @@ public class SaSsoTemplate {
|
|||||||
|
|
||||||
// step.1 遍历通知 Client 端注销会话
|
// step.1 遍历通知 Client 端注销会话
|
||||||
SaSsoConfig cfg = SaSsoManager.getConfig();
|
SaSsoConfig cfg = SaSsoManager.getConfig();
|
||||||
Set<String> urlSet = session.get(SaSsoConsts.SLO_CALLBACK_SET_KEY, () -> new HashSet<String>());
|
Set<String> urlSet = session.get(SaSsoConsts.SLO_CALLBACK_SET_KEY, HashSet::new);
|
||||||
for (String url : urlSet) {
|
for (String url : urlSet) {
|
||||||
url = addSignParams(url, loginId);
|
url = addSignParams(url, loginId);
|
||||||
cfg.getSendHttp().apply(url);
|
cfg.getSendHttp().apply(url);
|
||||||
@@ -315,12 +309,23 @@ public class SaSsoTemplate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取:账号资料
|
* 根据配置的 getData 地址,查询数据
|
||||||
* @param loginId 账号id
|
* @param paramMap 查询参数
|
||||||
* @return 账号资料
|
* @return 查询结果
|
||||||
*/
|
*/
|
||||||
public Object getUserinfo(Object loginId) {
|
public Object getData(Map<String, Object> paramMap) {
|
||||||
String url = buildUserinfoUrl(loginId);
|
String getDataUrl = SaSsoManager.getConfig().splicingGetDataUrl();
|
||||||
|
return getData(getDataUrl, paramMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据自定义 path 地址,查询数据 (此方法需要配置 sa-token.sso.server-url 地址)
|
||||||
|
* @param path 自定义 path
|
||||||
|
* @param paramMap 查询参数
|
||||||
|
* @return 查询结果
|
||||||
|
*/
|
||||||
|
public Object getData(String path, Map<String, Object> paramMap) {
|
||||||
|
String url = buildCustomPathUrl(path, paramMap);
|
||||||
return SaSsoManager.getConfig().getSendHttp().apply(url);
|
return SaSsoManager.getConfig().getSendHttp().apply(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,17 +360,16 @@ public class SaSsoTemplate {
|
|||||||
* 部分 Servlet 版本 request.getRequestURL() 返回的 url 带有 query 参数,形如:http://domain.com?id=1,
|
* 部分 Servlet 版本 request.getRequestURL() 返回的 url 带有 query 参数,形如:http://domain.com?id=1,
|
||||||
* 如果不加判断会造成最终生成的 serverAuthUrl 带有双 back 参数 ,这个 if 判断正是为了解决此问题
|
* 如果不加判断会造成最终生成的 serverAuthUrl 带有双 back 参数 ,这个 if 判断正是为了解决此问题
|
||||||
*/
|
*/
|
||||||
if(clientLoginUrl.indexOf(paramName.back + "=" + back) == -1) {
|
if( ! clientLoginUrl.contains(paramName.back + "=" + back) ) {
|
||||||
clientLoginUrl = SaFoxUtil.joinParam(clientLoginUrl, paramName.back, back);
|
clientLoginUrl = SaFoxUtil.joinParam(clientLoginUrl, paramName.back, back);
|
||||||
}
|
}
|
||||||
String serverAuthUrl = SaFoxUtil.joinParam(serverUrl, paramName.redirect, clientLoginUrl);
|
|
||||||
|
|
||||||
// 返回
|
// 返回
|
||||||
return serverAuthUrl;
|
return SaFoxUtil.joinParam(serverUrl, paramName.redirect, clientLoginUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建URL:Server端向Client下放ticke的地址
|
* 构建URL:Server端向Client下放ticket的地址
|
||||||
* @param loginId 账号id
|
* @param loginId 账号id
|
||||||
* @param client 客户端标识
|
* @param client 客户端标识
|
||||||
* @param redirect Client端提供的重定向地址
|
* @param redirect Client端提供的重定向地址
|
||||||
@@ -412,16 +416,6 @@ public class SaSsoTemplate {
|
|||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建URL:Server端 账号资料查询地址
|
|
||||||
* @param loginId 账号id
|
|
||||||
* @return Server端 账号资料查询地址
|
|
||||||
*/
|
|
||||||
public String buildUserinfoUrl(Object loginId) {
|
|
||||||
String userinfoUrl = SaSsoManager.getConfig().splicingUserinfoUrl();
|
|
||||||
return addSignParams(userinfoUrl, loginId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建URL:校验ticket的URL
|
* 构建URL:校验ticket的URL
|
||||||
* <p> 在模式三下,Client端拿到Ticket后根据此地址向Server端发送请求,获取账号id
|
* <p> 在模式三下,Client端拿到Ticket后根据此地址向Server端发送请求,获取账号id
|
||||||
@@ -461,6 +455,34 @@ public class SaSsoTemplate {
|
|||||||
return addSignParams(url, loginId);
|
return addSignParams(url, loginId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建URL:Server端 getData 地址,带签名等参数
|
||||||
|
* @param paramMap 查询参数
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public String buildGetDataUrl(Map<String, Object> paramMap) {
|
||||||
|
String getDataUrl = SaSsoManager.getConfig().getGetDataUrl();
|
||||||
|
return buildCustomPathUrl(getDataUrl, paramMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建URL:Server 端自定义 path 地址,带签名等参数 (此方法需要配置 sa-token.sso.server-url 地址)
|
||||||
|
* @param paramMap 请求参数
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public String buildCustomPathUrl(String path, Map<String, Object> paramMap) {
|
||||||
|
// 如果path不是以 http 开头,那么就拼接上 serverUrl
|
||||||
|
String url = path;
|
||||||
|
if( ! url.startsWith("http") ) {
|
||||||
|
String serverUrl = SaSsoManager.getConfig().getServerUrl();
|
||||||
|
SaSsoException.throwByNull(serverUrl, "请先配置 sa-token.sso.server-url 地址", SaSsoErrorCode.CODE_30012);
|
||||||
|
url = SaFoxUtil.spliceTwoUrl(serverUrl, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加签名等参数,并序列化
|
||||||
|
return addSignParams(url, paramMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------- 返回相应key -------------------
|
// ------------------- 返回相应key -------------------
|
||||||
|
|
||||||
@@ -510,24 +532,65 @@ public class SaSsoTemplate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验secretkey秘钥是否有效 (API已过期,请更改为更安全的 sign 式校验)
|
* 给 paramMap 追加 sign 等参数,并序列化为kv字符串,拼接到url后面
|
||||||
* @param secretkey 秘钥
|
* @param url 请求地址
|
||||||
|
* @param paramMap 请求原始参数列表
|
||||||
|
* @return 加工后的url
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
public String addSignParams(String url, Map<String, Object> paramMap) {
|
||||||
public void checkSecretkey(String secretkey) {
|
// 追加:时间戳、随机字符串、参数签名
|
||||||
if(SaFoxUtil.isEmpty(secretkey) || secretkey.equals(getSecretkey()) == false) {
|
SaManager.getSaSignTemplate().addSignParams(paramMap, getSecretkey());
|
||||||
throw new SaSsoException("无效秘钥:" + secretkey).setCode(SaSsoErrorCode.CODE_30003);
|
|
||||||
}
|
// 序列化为kv字符串
|
||||||
|
String signParams = SaManager.getSaSignTemplate().joinParams(paramMap);
|
||||||
|
|
||||||
|
// 拼接到一起
|
||||||
|
return SaFoxUtil.joinParam(url, signParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据参数计算签名
|
* 给 url 拼接 loginId 参数,并拼接 sign 等参数
|
||||||
|
* @param url 链接
|
||||||
|
* @param loginId 账号id
|
||||||
|
* @return 加工后的url
|
||||||
|
*/
|
||||||
|
public String addSignParams(String url, Object loginId) {
|
||||||
|
Map<String, Object> paramMap = new LinkedHashMap<>();
|
||||||
|
paramMap.put(paramName.loginId, loginId);
|
||||||
|
return addSignParams(url, paramMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验签名
|
||||||
|
* @param req request
|
||||||
|
*/
|
||||||
|
public void checkSign(SaRequest req) {
|
||||||
|
// 获取签名、时间戳、随机字符串
|
||||||
|
String sign = req.getParamNotNull(paramName.sign);
|
||||||
|
String timestamp = req.getParamNotNull(paramName.timestamp);
|
||||||
|
String nonce = req.getParamNotNull(paramName.nonce);
|
||||||
|
|
||||||
|
// 1、校验时间戳
|
||||||
|
SaManager.getSaSignTemplate().checkTimestamp(Long.parseLong(timestamp), SaSsoManager.getConfig().getTimestampDisparity());
|
||||||
|
|
||||||
|
// 2、校验随机字符串
|
||||||
|
|
||||||
|
// 3、校验签名
|
||||||
|
SaManager.getSaSignTemplate().checkSign(req.getParamMap(), getSecretkey(), sign);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------- 以下方法已废弃,仅为兼容旧版本而保留 --------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据参数计算签名
|
||||||
* @param loginId 账号id
|
* @param loginId 账号id
|
||||||
* @param timestamp 当前时间戳,13位
|
* @param timestamp 当前时间戳,13位
|
||||||
* @param nonce 随机字符串
|
* @param nonce 随机字符串
|
||||||
* @param secretkey 账号id
|
* @param secretkey 账号id
|
||||||
* @return 签名
|
* @return 签名
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public String getSign(Object loginId, String timestamp, String nonce, String secretkey) {
|
public String getSign(Object loginId, String timestamp, String nonce, String secretkey) {
|
||||||
Map<String, Object> map = new TreeMap<>();
|
Map<String, Object> map = new TreeMap<>();
|
||||||
map.put(paramName.loginId, loginId);
|
map.put(paramName.loginId, loginId);
|
||||||
@@ -537,58 +600,26 @@ public class SaSsoTemplate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 给 url 追加 sign 等参数
|
* 构建URL:Server端 账号资料查询地址
|
||||||
* @param url 连接
|
* @param loginId 账号id
|
||||||
* @param loginId 账号id
|
* @return Server端 账号资料查询地址
|
||||||
* @return 加工后的url
|
|
||||||
*/
|
*/
|
||||||
public String addSignParams(String url, Object loginId) {
|
@Deprecated
|
||||||
|
public String buildUserinfoUrl(Object loginId) {
|
||||||
// 时间戳、随机字符串、参数签名
|
String userinfoUrl = SaSsoManager.getConfig().splicingUserinfoUrl();
|
||||||
String timestamp = String.valueOf(System.currentTimeMillis());
|
return addSignParams(userinfoUrl, loginId);
|
||||||
String nonce = SaFoxUtil.getRandomString(20);
|
|
||||||
String sign = getSign(loginId, timestamp, nonce, getSecretkey());
|
|
||||||
|
|
||||||
// 追加到url
|
|
||||||
url = SaFoxUtil.joinParam(url, paramName.loginId, loginId);
|
|
||||||
url = SaFoxUtil.joinParam(url, paramName.timestamp, timestamp);
|
|
||||||
url = SaFoxUtil.joinParam(url, paramName.nonce, nonce);
|
|
||||||
url = SaFoxUtil.joinParam(url, paramName.sign, sign);
|
|
||||||
return url;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验签名
|
* 获取:账号资料
|
||||||
* @param req request
|
* @param loginId 账号id
|
||||||
|
* @return 账号资料
|
||||||
*/
|
*/
|
||||||
public void checkSign(SaRequest req) {
|
@Deprecated
|
||||||
|
public Object getUserinfo(Object loginId) {
|
||||||
// 参数签名、账号id、时间戳、随机字符串
|
String url = buildUserinfoUrl(loginId);
|
||||||
String sign = req.getParamNotNull(paramName.sign);
|
return SaSsoManager.getConfig().getSendHttp().apply(url);
|
||||||
String loginId = req.getParamNotNull(paramName.loginId);
|
|
||||||
String timestamp = req.getParamNotNull(paramName.timestamp);
|
|
||||||
String nonce = req.getParamNotNull(paramName.nonce);
|
|
||||||
|
|
||||||
// 校验时间戳
|
|
||||||
checkTimestamp(Long.valueOf(timestamp));
|
|
||||||
|
|
||||||
// 校验签名
|
|
||||||
String calcSign = getSign(loginId, timestamp, nonce, getSecretkey());
|
|
||||||
if(calcSign.equals(sign) == false) {
|
|
||||||
throw new SaSsoException("签名无效:" + calcSign).setCode(SaSsoErrorCode.CODE_30008);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 校验时间戳与当前时间的差距是否超出限制
|
|
||||||
* @param timestamp 时间戳
|
|
||||||
*/
|
|
||||||
public void checkTimestamp(long timestamp) {
|
|
||||||
long disparity = Math.abs(System.currentTimeMillis() - timestamp);
|
|
||||||
long allowDisparity = SaSsoManager.getConfig().getTimestampDisparity();
|
|
||||||
if(allowDisparity != -1 && disparity > allowDisparity) {
|
|
||||||
throw new SaSsoException("timestamp 超出允许的范围").setCode(SaSsoErrorCode.CODE_30007);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,8 @@ package cn.dev33.satoken.sso;
|
|||||||
import cn.dev33.satoken.context.model.SaRequest;
|
import cn.dev33.satoken.context.model.SaRequest;
|
||||||
import cn.dev33.satoken.util.SaResult;
|
import cn.dev33.satoken.util.SaResult;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sa-Token-SSO 单点登录模块 工具类
|
* Sa-Token-SSO 单点登录模块 工具类
|
||||||
* @author kong
|
* @author kong
|
||||||
@@ -139,12 +141,22 @@ public class SaSsoUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取:账号资料
|
* 获取:查询数据
|
||||||
* @param loginId 账号id
|
* @param paramMap 查询参数
|
||||||
* @return 账号资料
|
* @return 查询结果
|
||||||
*/
|
*/
|
||||||
public static Object getUserinfo(Object loginId) {
|
public static Object getData(Map<String, Object> paramMap) {
|
||||||
return ssoTemplate.getUserinfo(loginId);
|
return ssoTemplate.getData(paramMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据自定义 path 查询数据 (此方法需要配置 sa-token.sso.server-url 地址)
|
||||||
|
* @param path 自定义 path
|
||||||
|
* @param paramMap 查询参数
|
||||||
|
* @return 查询结果
|
||||||
|
*/
|
||||||
|
public static Object getData(String path, Map<String, Object> paramMap) {
|
||||||
|
return ssoTemplate.getData(path, paramMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -161,7 +173,7 @@ public class SaSsoUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建URL:Server端向Client下放ticke的地址
|
* 构建URL:Server端向Client下放ticket的地址
|
||||||
* @param loginId 账号id
|
* @param loginId 账号id
|
||||||
* @param client 客户端标识
|
* @param client 客户端标识
|
||||||
* @param redirect Client端提供的重定向地址
|
* @param redirect Client端提供的重定向地址
|
||||||
@@ -172,14 +184,23 @@ public class SaSsoUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建URL:Server端 账号资料查询地址
|
* 构建URL:Server端 getData 地址,带签名等参数
|
||||||
* @param loginId 账号id
|
* @param paramMap 查询参数
|
||||||
* @return Server端 账号资料查询地址
|
* @return /
|
||||||
*/
|
*/
|
||||||
public static String buildUserinfoUrl(Object loginId) {
|
public static String buildGetDataUrl(Map<String, Object> paramMap) {
|
||||||
return ssoTemplate.buildUserinfoUrl(loginId);
|
return ssoTemplate.buildGetDataUrl(paramMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建URL:Server 端自定义 path 地址,带签名等参数 (此方法需要配置 sa-token.sso.server-url 地址)
|
||||||
|
* @param paramMap 请求参数
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static String buildCustomPathUrl(String path, Map<String, Object> paramMap) {
|
||||||
|
return ssoTemplate.buildCustomPathUrl(path, paramMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------- 请求相关 -------------------
|
// ------------------- 请求相关 -------------------
|
||||||
|
|
||||||
@@ -193,31 +214,20 @@ public class SaSsoUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验secretkey秘钥是否有效 (API已过期,请更改为更安全的 sign 式校验)
|
* 给 paramMap 追加 sign 等参数,并序列化为kv字符串,拼接到url后面
|
||||||
* @param secretkey 秘钥
|
* @param url 请求地址
|
||||||
|
* @param paramMap 请求原始参数列表
|
||||||
|
* @return 加工后的url
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
public static String addSignParams(String url, Map<String, Object> paramMap) {
|
||||||
public static void checkSecretkey(String secretkey) {
|
return ssoTemplate.addSignParams(url, paramMap);
|
||||||
ssoTemplate.checkSecretkey(secretkey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据参数计算签名
|
* 给 url 拼接 loginId 参数,并拼接 sign 等参数
|
||||||
|
* @param url 链接
|
||||||
* @param loginId 账号id
|
* @param loginId 账号id
|
||||||
* @param timestamp 当前时间戳,13位
|
* @return 加工后的url
|
||||||
* @param nonce 随机字符串
|
|
||||||
* @param secretkey 账号id
|
|
||||||
* @return 签名
|
|
||||||
*/
|
|
||||||
public static String getSign(Object loginId, String timestamp, String nonce, String secretkey) {
|
|
||||||
return ssoTemplate.getSign(loginId, timestamp, nonce, secretkey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 给 url 追加 sign 等参数
|
|
||||||
* @param url 连接
|
|
||||||
* @param loginId 账号id
|
|
||||||
* @return 加工后的url
|
|
||||||
*/
|
*/
|
||||||
public static String addSignParams(String url, Object loginId) {
|
public static String addSignParams(String url, Object loginId) {
|
||||||
return ssoTemplate.addSignParams(url, loginId);
|
return ssoTemplate.addSignParams(url, loginId);
|
||||||
@@ -231,12 +241,40 @@ public class SaSsoUtil {
|
|||||||
ssoTemplate.checkSign(req);
|
ssoTemplate.checkSign(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------- 以下方法已废弃,仅为兼容旧版本而保留 --------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验时间戳与当前时间的差距是否超出限制
|
* 根据参数计算签名
|
||||||
* @param timestamp 时间戳
|
* @param loginId 账号id
|
||||||
|
* @param timestamp 当前时间戳,13位
|
||||||
|
* @param nonce 随机字符串
|
||||||
|
* @param secretkey 账号id
|
||||||
|
* @return 签名
|
||||||
*/
|
*/
|
||||||
public static void checkTimestamp(long timestamp) {
|
@Deprecated
|
||||||
ssoTemplate.checkTimestamp(timestamp);
|
public static String getSign(Object loginId, String timestamp, String nonce, String secretkey) {
|
||||||
|
return ssoTemplate.getSign(loginId, timestamp, nonce, secretkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取:账号资料
|
||||||
|
* @param loginId 账号id
|
||||||
|
* @return 账号资料
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public static Object getUserinfo(Object loginId) {
|
||||||
|
return ssoTemplate.getUserinfo(loginId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建URL:Server端 账号资料查询地址
|
||||||
|
* @param loginId 账号id
|
||||||
|
* @return Server端 账号资料查询地址
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public static String buildUserinfoUrl(Object loginId) {
|
||||||
|
return ssoTemplate.buildUserinfoUrl(loginId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -40,5 +40,8 @@ public interface SaSsoErrorCode {
|
|||||||
|
|
||||||
/** 该 ticket 不属于当前 client */
|
/** 该 ticket 不属于当前 client */
|
||||||
public static final int CODE_30011 = 30011;
|
public static final int CODE_30011 = 30011;
|
||||||
|
|
||||||
|
/** 当前缺少配置 server-url 地址 */
|
||||||
|
public static final int CODE_30012 = 30012;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,5 @@
|
|||||||
package cn.dev33.satoken.servlet.model;
|
package cn.dev33.satoken.servlet.model;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import cn.dev33.satoken.SaManager;
|
import cn.dev33.satoken.SaManager;
|
||||||
import cn.dev33.satoken.context.model.SaRequest;
|
import cn.dev33.satoken.context.model.SaRequest;
|
||||||
import cn.dev33.satoken.exception.SaTokenException;
|
import cn.dev33.satoken.exception.SaTokenException;
|
||||||
@@ -12,6 +10,9 @@ import jakarta.servlet.http.Cookie;
|
|||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request for Jakarta Servlet
|
* Request for Jakarta Servlet
|
||||||
* @author kong
|
* @author kong
|
||||||
@@ -48,6 +49,36 @@ public class SaRequestForServlet implements SaRequest {
|
|||||||
return request.getParameter(name);
|
return request.getParameter(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [请求体] 里提交的所有参数名称
|
||||||
|
* @return 参数名称列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<String> getParamNames(){
|
||||||
|
Enumeration<String> parameterNames = request.getParameterNames();
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
while (parameterNames.hasMoreElements()) {
|
||||||
|
list.add(parameterNames.nextElement());
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [请求体] 里提交的所有参数
|
||||||
|
* @return 参数列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getParamMap(){
|
||||||
|
// 获取所有参数
|
||||||
|
Map<String, String[]> parameterMap = request.getParameterMap();
|
||||||
|
Map<String, String> map = new LinkedHashMap<>(parameterMap.size());
|
||||||
|
for (String key : parameterMap.keySet()) {
|
||||||
|
String[] values = parameterMap.get(key);
|
||||||
|
map.put(key, values[0]);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在 [请求头] 里获取一个值
|
* 在 [请求头] 里获取一个值
|
||||||
*/
|
*/
|
||||||
|
@@ -12,6 +12,8 @@ import cn.dev33.satoken.reactor.context.SaReactorHolder;
|
|||||||
import cn.dev33.satoken.reactor.context.SaReactorSyncHolder;
|
import cn.dev33.satoken.reactor.context.SaReactorSyncHolder;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request for Reactor
|
* Request for Reactor
|
||||||
* @author kong
|
* @author kong
|
||||||
@@ -48,6 +50,25 @@ public class SaRequestForReactor implements SaRequest {
|
|||||||
return request.getQueryParams().getFirst(name);
|
return request.getQueryParams().getFirst(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [请求体] 里提交的所有参数名称
|
||||||
|
* @return 参数名称列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<String> getParamNames(){
|
||||||
|
Set<String> names = request.getQueryParams().keySet();
|
||||||
|
return new ArrayList<>(names);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [请求体] 里提交的所有参数
|
||||||
|
* @return 参数列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getParamMap(){
|
||||||
|
return request.getQueryParams().toSingleValueMap();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在 [请求头] 里获取一个值
|
* 在 [请求头] 里获取一个值
|
||||||
*/
|
*/
|
||||||
|
@@ -12,6 +12,11 @@ import cn.dev33.satoken.reactor.context.SaReactorHolder;
|
|||||||
import cn.dev33.satoken.reactor.context.SaReactorSyncHolder;
|
import cn.dev33.satoken.reactor.context.SaReactorSyncHolder;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request for Reactor
|
* Request for Reactor
|
||||||
* @author kong
|
* @author kong
|
||||||
@@ -48,6 +53,25 @@ public class SaRequestForReactor implements SaRequest {
|
|||||||
return request.getQueryParams().getFirst(name);
|
return request.getQueryParams().getFirst(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [请求体] 里提交的所有参数名称
|
||||||
|
* @return 参数名称列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<String> getParamNames(){
|
||||||
|
Set<String> names = request.getQueryParams().keySet();
|
||||||
|
return new ArrayList<>(names);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [请求体] 里提交的所有参数
|
||||||
|
* @return 参数列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getParamMap(){
|
||||||
|
return request.getQueryParams().toSingleValueMap();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在 [请求头] 里获取一个值
|
* 在 [请求头] 里获取一个值
|
||||||
*/
|
*/
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package cn.dev33.satoken.servlet.model;
|
package cn.dev33.satoken.servlet.model;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.Cookie;
|
import javax.servlet.http.Cookie;
|
||||||
@@ -49,6 +50,36 @@ public class SaRequestForServlet implements SaRequest {
|
|||||||
return request.getParameter(name);
|
return request.getParameter(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [请求体] 里提交的所有参数名称
|
||||||
|
* @return 参数名称列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<String> getParamNames(){
|
||||||
|
Enumeration<String> parameterNames = request.getParameterNames();
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
while (parameterNames.hasMoreElements()) {
|
||||||
|
list.add(parameterNames.nextElement());
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [请求体] 里提交的所有参数
|
||||||
|
* @return 参数列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getParamMap(){
|
||||||
|
// 获取所有参数
|
||||||
|
Map<String, String[]> parameterMap = request.getParameterMap();
|
||||||
|
Map<String, String> map = new LinkedHashMap<>(parameterMap.size());
|
||||||
|
for (String key : parameterMap.keySet()) {
|
||||||
|
String[] values = parameterMap.get(key);
|
||||||
|
map.put(key, values[0]);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在 [请求头] 里获取一个值
|
* 在 [请求头] 里获取一个值
|
||||||
*/
|
*/
|
||||||
|
@@ -5,6 +5,11 @@ import cn.dev33.satoken.context.model.SaRequest;
|
|||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
import org.noear.solon.core.handle.Context;
|
import org.noear.solon.core.handle.Context;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author noear
|
* @author noear
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
@@ -27,6 +32,21 @@ public class SaRequestForSolon implements SaRequest {
|
|||||||
return ctx.param(s);
|
return ctx.param(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getParamNames(){
|
||||||
|
Set<String> names = ctx.paramMap().keySet();
|
||||||
|
return new ArrayList<>(names);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 [请求体] 里提交的所有参数
|
||||||
|
* @return 参数列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getParamMap(){
|
||||||
|
return ctx.paramMap();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getHeader(String s) {
|
public String getHeader(String s) {
|
||||||
return ctx.header(s);
|
return ctx.header(s);
|
||||||
|
Reference in New Issue
Block a user