将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

@@ -4,7 +4,6 @@ import java.util.Map;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.jwt.JWT;
@@ -53,9 +52,6 @@ public class SaJwtUtil {
*/
public static String createToken(Object loginId, Map<String, Object> extraData, String keyt) {
// 秘钥不可以为空
SaTokenException.throwByNull(keyt, "请配置jwt秘钥");
// 构建
String token = JWT.create()
.setPayload(LOGIN_ID, loginId)
@@ -82,9 +78,6 @@ public class SaJwtUtil {
public static String createToken(String loginType, Object loginId, String device,
long timeout, Map<String, Object> extraData, String keyt) {
// 秘钥不可以为空
SaTokenException.throwByNull(keyt, "请配置jwt秘钥");
// 计算有效期
long effTime = timeout;
if(timeout != NEVER_EXPIRE) {
@@ -112,9 +105,7 @@ public class SaJwtUtil {
* @return 解析后的jwt 对象
*/
public static JWT parseToken(String token, String keyt) {
// 秘钥不可以为空
SaTokenException.throwByNull(keyt, "请配置jwt秘钥");
// 如果token为null
if(token == null) {
throw NotLoginException.newInstance(null, NotLoginException.NOT_TOKEN);

View File

@@ -7,6 +7,7 @@ import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.exception.ApiDisabledException;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
@@ -38,7 +39,9 @@ public class StpLogicJwtForMix extends StpLogic {
* @return /
*/
public String jwtSecretKey() {
return getConfig().getJwtSecretKey();
String keyt = getConfig().getJwtSecretKey();
SaTokenException.throwByNull(keyt, "请配置jwt秘钥");
return keyt;
}
//

View File

@@ -40,7 +40,9 @@ public class StpLogicJwtForStateless extends StpLogic {
* @return /
*/
public String jwtSecretKey() {
return getConfig().getJwtSecretKey();
String keyt = getConfig().getJwtSecretKey();
SaTokenException.throwByNull(keyt, "请配置jwt秘钥");
return keyt;
}
//

View File

@@ -2,6 +2,7 @@ package cn.dev33.satoken.jwt;
import java.util.Map;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
@@ -32,7 +33,9 @@ public class StpLogicJwtForStyle extends StpLogic {
* @return /
*/
public String jwtSecretKey() {
return getConfig().getJwtSecretKey();
String keyt = getConfig().getJwtSecretKey();
SaTokenException.throwByNull(keyt, "请配置jwt秘钥");
return keyt;
}
// ------ 重写方法

View File

@@ -91,6 +91,14 @@ public class SaSsoConfig implements Serializable {
public String ssoLogoutCall;
// ----------------- 其它
/**
* 接口调用时的时间戳允许的差距单位ms-1代表不校验差距
*/
public long timestampDisparity = 1000 * 60 * 10;
/**
@@ -253,12 +261,37 @@ public class SaSsoConfig implements Serializable {
return this;
}
/**
* @return 接口调用时的时间戳允许的差距单位ms-1代表不校验差距
*/
public long getTimestampDisparity() {
return timestampDisparity;
}
/**
* @param timestampDisparity 接口调用时的时间戳允许的差距单位ms-1代表不校验差距
* @return 对象自身
*/
public SaSsoConfig setTimestampDisparity(long timestampDisparity) {
this.timestampDisparity = timestampDisparity;
return this;
}
@Override
public String toString() {
return "SaSsoConfig [ticketTimeout=" + ticketTimeout + ", allowUrl=" + allowUrl + ", isSlo=" + isSlo
+ ", isHttp=" + isHttp + ", secretkey=" + secretkey + ", authUrl=" + authUrl + ", checkTicketUrl="
+ checkTicketUrl + ", userinfoUrl=" + userinfoUrl + ", sloUrl=" + sloUrl + ", ssoLogoutCall="
+ ssoLogoutCall + "]";
return "SaSsoConfig ["
+ "ticketTimeout=" + ticketTimeout
+ ", allowUrl=" + allowUrl
+ ", isSlo=" + isSlo
+ ", isHttp=" + isHttp
+ ", secretkey=" + secretkey
+ ", authUrl=" + authUrl
+ ", checkTicketUrl=" + checkTicketUrl
+ ", userinfoUrl=" + userinfoUrl
+ ", sloUrl=" + sloUrl
+ ", ssoLogoutCall=" + ssoLogoutCall
+ ", timestampDisparity=" + timestampDisparity
+ "]";
}
/**

View File

@@ -62,6 +62,10 @@ public class SaSsoConsts {
public static String name = "name";
public static String pwd = "pwd";
public static String timestamp = "timestamp";
public static String nonce = "nonce";
public static String sign = "sign";
}

View File

@@ -1,8 +1,5 @@
package cn.dev33.satoken.sso;
import java.util.Map;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.config.SaSsoConfig;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaRequest;
@@ -110,15 +107,13 @@ public class SaSsoHandle {
}
/**
* SSO-Server端校验ticket 获取账号id
* SSO-Server端校验ticket 获取账号id [模式三]
* @return 处理结果
*/
public static Object ssoCheckTicket() {
// 获取对象
SaRequest req = SaHolder.getRequest();
// 获取参数
String ticket = req.getParam(ParamName.ticket);
SaRequest req = SaHolder.getRequest();
String ticket = req.getParamNotNull(ParamName.ticket);
String sloCallback = req.getParam(ParamName.ssoLogoutCall);
// 校验ticket获取 loginId
@@ -143,15 +138,12 @@ public class SaSsoHandle {
// 获取对象
SaRequest req = SaHolder.getRequest();
SaResponse res = SaHolder.getResponse();
SaSsoConfig cfg = SaSsoManager.getConfig();
StpLogic stpLogic = SaSsoUtil.saSsoTemplate.stpLogic;
String loginId = req.getParam(ParamName.loginId);
Object loginId = SaSsoUtil.saSsoTemplate.stpLogic.getLoginIdDefaultNull();
// step.1 遍历 Client 端注销
SaSsoUtil.forEachSloUrl(loginId, url -> cfg.getSendHttp().apply(url));
// step.2 Server 端注销
stpLogic.logout();
// 单点注销
if(SaFoxUtil.isNotEmpty(loginId)) {
SaSsoUtil.ssoLogout(loginId);
}
// 完成
return ssoLogoutBack(req, res);
@@ -162,25 +154,17 @@ public class SaSsoHandle {
* @return 处理结果
*/
public static Object ssoLogoutByClientHttp() {
// 获取对象
SaRequest req = SaHolder.getRequest();
SaSsoConfig cfg = SaSsoManager.getConfig();
StpLogic stpLogic = SaSsoUtil.saSsoTemplate.stpLogic;
// 获取参数
SaRequest req = SaHolder.getRequest();
String loginId = req.getParam(ParamName.loginId);
String secretkey = req.getParam(ParamName.secretkey);
// step.1 校验秘钥
SaSsoUtil.checkSecretkey(secretkey);
// step.1 校验签名
SaSsoUtil.checkSign(req);
// step.2 遍历 Client 端注销
SaSsoUtil.forEachSloUrl(loginId, url -> cfg.getSendHttp().apply(url));
// step.3 Server 端注销
stpLogic.logout(loginId);
// 完成
// step.2 单点注销
SaSsoUtil.ssoLogout(loginId);
// 响应
return SaResult.ok();
}
@@ -302,12 +286,16 @@ public class SaSsoHandle {
return SaResult.ok();
}
// 调用SSO-Server认证中心API进行注销
// 调用 sso-server 认证中心单点注销API
String url = SaSsoUtil.buildSloUrl(stpLogic.getLoginId());
SaResult result = request(url);
SaResult result = SaSsoUtil.request(url);
// 校验
// 校验响应状态码
if(result.getCode() == SaResult.CODE_SUCCESS) {
// 极端场景下sso-server 中心的单点注销可能并不会通知到此 client 端,所以这里需要再补一刀
if(stpLogic.isLogin()) {
stpLogic.logout();
}
return ssoLogoutBack(req, res);
} else {
// 将 sso-server 回应的消息作为异常抛出
@@ -325,11 +313,10 @@ public class SaSsoHandle {
StpLogic stpLogic = SaSsoUtil.saSsoTemplate.stpLogic;
// 获取参数
String loginId = req.getParam(ParamName.loginId);
String secretkey = req.getParam(ParamName.secretkey);
String loginId = req.getParamNotNull(ParamName.loginId);
// 注销当前应用端会话
SaSsoUtil.checkSecretkey(secretkey);
SaSsoUtil.checkSign(req);
stpLogic.logout(loginId);
// 响应
@@ -382,7 +369,7 @@ public class SaSsoHandle {
// 发起请求
String checkUrl = SaSsoUtil.buildCheckTicketUrl(ticket, ssoLogoutCall);
SaResult result = request(checkUrl);
SaResult result = SaSsoUtil.request(checkUrl);
// 校验
if(result.getCode() == SaResult.CODE_SUCCESS) {
@@ -397,15 +384,4 @@ public class SaSsoHandle {
}
}
/**
* 发出请求,并返回 SaResult 结果
* @param url 请求地址
* @return 返回的结果
*/
public static SaResult request(String url) {
String body = SaSsoManager.getConfig().getSendHttp().apply(url);
Map<String, Object> map = SaManager.getSaJsonTemplate().parseJsonToMap(body);
return new SaResult(map);
}
}

View File

@@ -3,10 +3,13 @@ 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.config.SaSsoConfig;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.sso.SaSsoConsts.ParamName;
import cn.dev33.satoken.sso.exception.SaSsoException;
@@ -14,6 +17,7 @@ import cn.dev33.satoken.sso.exception.SaSsoExceptionCode;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaResult;
/**
* Sa-Token-SSO 单点登录模块
@@ -149,6 +153,94 @@ public class SaSsoTemplate {
return SaFoxUtil.getRandomString(64);
}
/**
* 获取:所有允许的授权回调地址,多个用逗号隔开 (不在此列表中的URL将禁止下放ticket)
* @return see note
*/
public String getAllowUrl() {
// 默认从配置文件中返回
return SaSsoManager.getConfig().getAllowUrl();
}
/**
* 校验重定向url合法性
* @param url 下放ticket的url地址
*/
public void checkRedirectUrl(String url) {
// 1、是否是一个有效的url
if(SaFoxUtil.isUrl(url) == false) {
throw new SaSsoException("无效redirect" + url).setCode(SaSsoExceptionCode.CODE_20001);
}
// 2、截取掉?后面的部分
int qIndex = url.indexOf("?");
if(qIndex != -1) {
url = url.substring(0, qIndex);
}
// 3、是否在[允许地址列表]之中
List<String> authUrlList = Arrays.asList(getAllowUrl().replaceAll(" ", "").split(","));
if(SaStrategy.me.hasElement.apply(authUrlList, url) == false) {
throw new SaSsoException("非法redirect" + url).setCode(SaSsoExceptionCode.CODE_20002);
}
// 校验通过 √
return;
}
// ------------------- SSO 模式三相关 -------------------
/**
* 为指定账号id注册单点注销回调URL
* @param loginId 账号id
* @param sloCallbackUrl 单点注销时的回调URL
*/
public void registerSloCallbackUrl(Object loginId, String sloCallbackUrl) {
if(SaFoxUtil.isEmpty(loginId) || SaFoxUtil.isEmpty(sloCallbackUrl)) {
return;
}
SaSession session = stpLogic.getSessionByLoginId(loginId);
Set<String> urlSet = session.get(SaSsoConsts.SLO_CALLBACK_SET_KEY, ()-> new HashSet<String>());
urlSet.add(sloCallbackUrl);
session.set(SaSsoConsts.SLO_CALLBACK_SET_KEY, urlSet);
}
/**
* 指定账号单点注销
* @param loginId 指定账号
*/
public void ssoLogout(Object loginId) {
// 如果这个账号尚未登录,则无操作
SaSession session = stpLogic.getSessionByLoginId(loginId, false);
if(session == null) {
return;
}
// step.1 遍历通知 Client 端注销会话
SaSsoConfig cfg = SaSsoManager.getConfig();
Set<String> urlSet = session.get(SaSsoConsts.SLO_CALLBACK_SET_KEY, () -> new HashSet<String>());
for (String url : urlSet) {
url = addSignParams(url, loginId);
cfg.getSendHttp().apply(url);
}
// step.2 Server端注销
stpLogic.logout(loginId);
}
/**
* 获取:账号资料
* @param loginId 账号id
* @return 账号资料
*/
public Object getUserinfo(Object loginId) {
String url = buildUserinfoUrl(loginId);
return SaSsoManager.getConfig().getSendHttp().apply(url);
}
// ---------------------- 构建URL ----------------------
@@ -202,43 +294,7 @@ public class SaSsoTemplate {
// 构建 授权重定向地址 Server端 根据此地址向 Client端 下放Ticket
return SaFoxUtil.joinParam(encodeBackParam(redirect), ParamName.ticket, ticket);
}
/**
* 校验重定向url合法性
* @param url 下放ticket的url地址
*/
public void checkRedirectUrl(String url) {
// 1、是否是一个有效的url
if(SaFoxUtil.isUrl(url) == false) {
throw new SaSsoException("无效redirect" + url).setCode(SaSsoExceptionCode.CODE_20001);
}
// 2、截取掉?后面的部分
int qIndex = url.indexOf("?");
if(qIndex != -1) {
url = url.substring(0, qIndex);
}
// 3、是否在[允许地址列表]之中
List<String> authUrlList = Arrays.asList(getAllowUrl().replaceAll(" ", "").split(","));
if(SaStrategy.me.hasElement.apply(authUrlList, url) == false) {
throw new SaSsoException("非法redirect" + url).setCode(SaSsoExceptionCode.CODE_20002);
}
// 校验通过 √
return;
}
/**
* 获取:所有允许的授权回调地址,多个用逗号隔开 (不在此列表中的URL将禁止下放ticket)
* @return see note
*/
public String getAllowUrl() {
// 默认从配置文件中返回
return SaSsoManager.getConfig().getAllowUrl();
}
/**
* 对url中的back参数进行URL编码, 解决超链接重定向后参数丢失的bug
* @param url url
@@ -271,27 +327,10 @@ public class SaSsoTemplate {
* @return Server端 账号资料查询地址
*/
public String buildUserinfoUrl(Object loginId) {
// 拼接
String userinfoUrl = SaSsoManager.getConfig().getUserinfoUrl();
userinfoUrl = SaFoxUtil.joinParam(userinfoUrl, ParamName.loginId, loginId);
userinfoUrl = SaFoxUtil.joinParam(userinfoUrl, ParamName.secretkey, SaSsoManager.getConfig().getSecretkey());
// 返回
return userinfoUrl;
return addSignParams(userinfoUrl, loginId);
}
// ------------------- SSO 模式三相关 -------------------
/**
* 校验secretkey秘钥是否有效
* @param secretkey 秘钥
*/
public void checkSecretkey(String secretkey) {
if(secretkey == null || secretkey.isEmpty() || secretkey.equals(SaSsoManager.getConfig().getSecretkey()) == false) {
throw new SaSsoException("无效秘钥:" + secretkey).setCode(SaSsoExceptionCode.CODE_20003);
}
}
/**
* 构建URL校验ticket的URL
* <p> 在模式三下Client端拿到Ticket后根据此地址向Server端发送请求获取账号id
@@ -314,43 +353,6 @@ public class SaSsoTemplate {
// 返回
return url;
}
/**
* 为指定账号id注册单点注销回调URL
* @param loginId 账号id
* @param sloCallbackUrl 单点注销时的回调URL
*/
public void registerSloCallbackUrl(Object loginId, String sloCallbackUrl) {
if(loginId == null || sloCallbackUrl == null || sloCallbackUrl.isEmpty()) {
return;
}
SaSession session = stpLogic.getSessionByLoginId(loginId);
Set<String> urlSet = session.get(SaSsoConsts.SLO_CALLBACK_SET_KEY, ()-> new HashSet<String>());
urlSet.add(sloCallbackUrl);
session.set(SaSsoConsts.SLO_CALLBACK_SET_KEY, urlSet);
}
/**
* 循环调用Client端单点注销回调
* @param loginId 账号id
* @param fun 调用方法
*/
public void forEachSloUrl(Object loginId, CallSloUrlFunction fun) {
SaSession session = stpLogic.getSessionByLoginId(loginId, false);
if(session == null) {
return;
}
String secretkey = SaSsoManager.getConfig().getSecretkey();
Set<String> urlSet = session.get(SaSsoConsts.SLO_CALLBACK_SET_KEY, () -> new HashSet<String>());
for (String url : urlSet) {
// 拼接login参数、秘钥参数
url = SaFoxUtil.joinParam(url, ParamName.loginId, loginId);
url = SaFoxUtil.joinParam(url, ParamName.secretkey, secretkey);
// 调用
fun.run(url);
}
}
/**
* 构建URL单点注销URL
@@ -358,42 +360,10 @@ public class SaSsoTemplate {
* @return 单点注销URL
*/
public String buildSloUrl(Object loginId) {
SaSsoConfig ssoConfig = SaSsoManager.getConfig();
String url = ssoConfig.getSloUrl();
url = SaFoxUtil.joinParam(url, ParamName.loginId, loginId);
url = SaFoxUtil.joinParam(url, ParamName.secretkey, ssoConfig.getSecretkey());
return url;
}
/**
* 指定账号单点注销
* @param secretkey 校验秘钥
* @param loginId 指定账号
* @param fun 调用方法
*/
public void singleLogout(String secretkey, Object loginId, CallSloUrlFunction fun) {
// step.1 校验秘钥
checkSecretkey(secretkey);
// step.2 遍历通知Client端注销会话
forEachSloUrl(loginId, fun);
// step.3 Server端注销
// StpUtil.logoutByLoginId(loginId);
stpLogic.logoutByTokenValue(stpLogic.getTokenValueByLoginId(loginId));
String url = SaSsoManager.getConfig().getSloUrl();
return addSignParams(url, loginId);
}
/**
* 获取:账号资料
* @param loginId 账号id
* @return 账号资料
*/
public Object getUserinfo(Object loginId) {
String url = buildUserinfoUrl(loginId);
return SaSsoManager.getConfig().getSendHttp().apply(url);
}
// ------------------- 返回相应key -------------------
@@ -415,17 +385,112 @@ public class SaSsoTemplate {
return SaManager.getConfig().getTokenName() + ":id-ticket:" + id;
}
// ------------------- 请求相关 -------------------
/**
* 单点注销回调函数
* @author kong
* 发出请求,并返回 SaResult 结果
* @param url 请求地址
* @return 返回的结果
*/
@FunctionalInterface
public static interface CallSloUrlFunction{
/**
* 调用function
* @param url 注销回调URL
*/
public void run(String url);
public SaResult request(String url) {
String body = SaSsoManager.getConfig().getSendHttp().apply(url);
Map<String, Object> map = SaManager.getSaJsonTemplate().parseJsonToMap(body);
return new SaResult(map);
}
/**
* 获取:接口调用秘钥
* @return see note
*/
public String getSecretkey() {
// 默认从配置文件中返回
String secretkey = SaSsoManager.getConfig().getSecretkey();
if(SaFoxUtil.isEmpty(secretkey)) {
throw new SaSsoException("请配置 secretkey 参数").setCode(SaSsoExceptionCode.CODE_20009);
}
return secretkey;
}
/**
* 校验secretkey秘钥是否有效 API已过期请更改为更安全的 sign 式校验)
* @param secretkey 秘钥
*/
@Deprecated
public void checkSecretkey(String secretkey) {
if(SaFoxUtil.isEmpty(secretkey) || secretkey.equals(getSecretkey()) == false) {
throw new SaSsoException("无效秘钥:" + secretkey).setCode(SaSsoExceptionCode.CODE_20003);
}
}
/**
* 根据参数计算签名
* @param loginId 账号id
* @param timestamp 当前时间戳13位
* @param nonce 随机字符串
* @param secretkey 账号id
* @return 签名
*/
public String getSign(Object loginId, String timestamp, String nonce, String secretkey) {
Map<String, Object> map = new TreeMap<>();
map.put(ParamName.loginId, loginId);
map.put(ParamName.timestamp, timestamp);
map.put(ParamName.nonce, nonce);
return SaManager.getSaSignTemplate().createSign(map, secretkey);
}
/**
* 给 url 追加 sign 等参数
* @param loginId
* @return 加工后的url
*/
public String addSignParams(String url, Object loginId) {
// 时间戳、随机字符串、参数签名
String timestamp = String.valueOf(System.currentTimeMillis());
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
*/
public void checkSign(SaRequest req) {
// 参数签名、账号id、时间戳、随机字符串
String sign = req.getParamNotNull(ParamName.sign);
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(SaSsoExceptionCode.CODE_20008);
}
}
/**
* 校验时间戳与当前时间的差距是否超出限制
* @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(SaSsoExceptionCode.CODE_20007);
}
}
}

View File

@@ -1,7 +1,8 @@
package cn.dev33.satoken.sso;
import cn.dev33.satoken.sso.SaSsoTemplate.CallSloUrlFunction;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
/**
* Sa-Token-SSO 单点登录模块 工具类
@@ -71,7 +72,71 @@ public class SaSsoUtil {
public static Object checkTicket(String ticket) {
return saSsoTemplate.checkTicket(ticket);
}
/**
* 获取:所有允许的授权回调地址,多个用逗号隔开 (不在此列表中的URL将禁止下放ticket)
* @return see note
*/
public static String getAllowUrl() {
return saSsoTemplate.getAllowUrl();
}
/**
* 校验重定向url合法性
* @param url 下放ticket的url地址
*/
public static void checkRedirectUrl(String url) {
saSsoTemplate.checkRedirectUrl(url);
}
// ------------------- SSO 模式三 -------------------
/**
* 构建URL校验ticket的URL
* @param ticket ticket码
* @param ssoLogoutCallUrl 单点注销时的回调URL
* @return 构建完毕的URL
*/
public static String buildCheckTicketUrl(String ticket, String ssoLogoutCallUrl) {
return saSsoTemplate.buildCheckTicketUrl(ticket, ssoLogoutCallUrl);
}
/**
* 为指定账号id注册单点注销回调URL
* @param loginId 账号id
* @param sloCallbackUrl 单点注销时的回调URL
*/
public static void registerSloCallbackUrl(Object loginId, String sloCallbackUrl) {
saSsoTemplate.registerSloCallbackUrl(loginId, sloCallbackUrl);
}
/**
* 构建URL单点注销URL
* @param loginId 要注销的账号id
* @return 单点注销URL
*/
public static String buildSloUrl(Object loginId) {
return saSsoTemplate.buildSloUrl(loginId);
}
/**
* 指定账号单点注销
* @param loginId 指定账号
*/
public static void ssoLogout(Object loginId) {
saSsoTemplate.ssoLogout(loginId);
}
/**
* 获取:账号资料
* @param loginId 账号id
* @return 账号资料
*/
public static Object getUserinfo(Object loginId) {
return saSsoTemplate.getUserinfo(loginId);
}
// ---------------------- 构建URL ----------------------
@@ -94,22 +159,6 @@ public class SaSsoUtil {
public static String buildRedirectUrl(Object loginId, String redirect) {
return saSsoTemplate.buildRedirectUrl(loginId, redirect);
}
/**
* 校验重定向url合法性
* @param url 下放ticket的url地址
*/
public static void checkRedirectUrl(String url) {
saSsoTemplate.checkRedirectUrl(url);
}
/**
* 获取:所有允许的授权回调地址,多个用逗号隔开 (不在此列表中的URL将禁止下放ticket)
* @return see note
*/
public static String getAllowUrl() {
return saSsoTemplate.getAllowUrl();
}
/**
* 构建URLServer端 账号资料查询地址
@@ -120,70 +169,62 @@ public class SaSsoUtil {
return saSsoTemplate.buildUserinfoUrl(loginId);
}
// ------------------- SSO 模式三 -------------------
// ------------------- 请求相关 -------------------
/**
* 校验secretkey秘钥是否有效
* 发出请求,并返回 SaResult 结果
* @param url 请求地址
* @return 返回的结果
*/
public static SaResult request(String url) {
return saSsoTemplate.request(url);
}
/**
* 校验secretkey秘钥是否有效 API已过期请更改为更安全的 sign 式校验)
* @param secretkey 秘钥
*/
@Deprecated
public static void checkSecretkey(String secretkey) {
saSsoTemplate.checkSecretkey(secretkey);
}
/**
* 构建URL校验ticket的URL
* @param ticket ticket码
* @param ssoLogoutCallUrl 单点注销时的回调URL
* @return 构建完毕的URL
*/
public static String buildCheckTicketUrl(String ticket, String ssoLogoutCallUrl) {
return saSsoTemplate.buildCheckTicketUrl(ticket, ssoLogoutCallUrl);
}
/**
* 为指定账号id注册单点注销回调URL
* 根据参数计算签名
* @param loginId 账号id
* @param sloCallbackUrl 单点注销时的回调URL
* @param timestamp 当前时间戳13位
* @param nonce 随机字符串
* @param secretkey 账号id
* @return 签名
*/
public static void registerSloCallbackUrl(Object loginId, String sloCallbackUrl) {
saSsoTemplate.registerSloCallbackUrl(loginId, sloCallbackUrl);
public static String getSign(Object loginId, String timestamp, String nonce, String secretkey) {
return saSsoTemplate.getSign(loginId, timestamp, nonce, secretkey);
}
/**
* 循环调用Client端单点注销回调
* @param loginId 账号id
* @param fun 调用方法
* 给 url 追加 sign 等参数
* @param loginId
* @return 加工后的url
*/
public static void forEachSloUrl(Object loginId, CallSloUrlFunction fun) {
saSsoTemplate.forEachSloUrl(loginId, fun);
public static String addSignParams(String url, Object loginId) {
return saSsoTemplate.addSignParams(url, loginId);
}
/**
* 构建URL单点注销URL
* @param loginId 要注销的账号id
* @return 单点注销URL
* 校验签名
* @param req request
*/
public static String buildSloUrl(Object loginId) {
return saSsoTemplate.buildSloUrl(loginId);
public static void checkSign(SaRequest req) {
saSsoTemplate.checkSign(req);
}
/**
* 指定账号单点注销
* @param secretkey 校验秘钥
* @param loginId 指定账号
* @param fun 调用方法
* 校验时间戳与当前时间的差距是否超出限制
* @param timestamp 时间戳
*/
public static void singleLogout(String secretkey, Object loginId, CallSloUrlFunction fun) {
saSsoTemplate.singleLogout(secretkey, loginId, fun);
}
/**
* 获取:账号资料
* @param loginId 账号id
* @return 账号资料
*/
public static Object getUserinfo(Object loginId) {
return saSsoTemplate.getUserinfo(loginId);
public static void checkTimestamp(long timestamp) {
saSsoTemplate.checkTimestamp(timestamp);
}
}

View File

@@ -25,5 +25,14 @@ public class SaSsoExceptionCode {
/** 在模式三下sso-client 调用 sso-server 端 单点注销接口 时,得到的响应是注销失败 */
public static final int CODE_20006 = 20006;
/** http 请求调用 提供的 timestamp 与当前时间的差距超出允许的范围 */
public static final int CODE_20007 = 20007;
/** http 请求调用 提供的 sign 无效 */
public static final int CODE_20008 = 20008;
/** 本地系统没有配置 secretkey 字段 */
public static final int CODE_20009 = 20009;
}