diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/config/SaSsoConfig.java b/sa-token-core/src/main/java/cn/dev33/satoken/config/SaSsoConfig.java index 7562e3ed..bd082404 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/config/SaSsoConfig.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/config/SaSsoConfig.java @@ -46,13 +46,19 @@ public class SaSsoConfig implements Serializable { /** * SSO-Server端 单点注销地址 */ - public String sloUrl; +// public String sloUrl; /** * SSO-Client端 当前Client端的单点注销回调URL (为空时自动获取) */ public String ssoLogoutCall; + /** + * SSO-Server端 账号资料查询地址 + */ + public String userinfoUrl; + + /** * @return Ticket有效期 (单位: 秒) @@ -132,22 +138,22 @@ public class SaSsoConfig implements Serializable { this.checkTicketUrl = checkTicketUrl; return this; } - - /** - * @return SSO-Server端单点注销地址 - */ - public String getSloUrl() { - return sloUrl; - } - - /** - * @param sloUrl SSO-Server端单点注销地址 - * @return 对象自身 - */ - public SaSsoConfig setSloUrl(String sloUrl) { - this.sloUrl = sloUrl; - return this; - } +// +// /** +// * @return SSO-Server端单点注销地址 +// */ +// public String getSloUrl() { +// return sloUrl; +// } +// +// /** +// * @param sloUrl SSO-Server端单点注销地址 +// * @return 对象自身 +// */ +// public SaSsoConfig setSloUrl(String sloUrl) { +// this.sloUrl = sloUrl; +// return this; +// } /** * @return SSO-Client端 当前Client端的单点注销回调URL (为空时自动获取) @@ -165,11 +171,27 @@ public class SaSsoConfig implements Serializable { return this; } + /** + * @return SSO-Server端 账号资料查询地址 + */ + public String getUserinfoUrl() { + return userinfoUrl; + } + + /** + * @param userinfoUrl SSO-Server端 账号资料查询地址 + * @return 对象自身 + */ + public SaSsoConfig setUserinfoUrl(String userinfoUrl) { + this.userinfoUrl = userinfoUrl; + return this; + } + @Override public String toString() { return "SaSsoConfig [ticketTimeout=" + ticketTimeout + ", allowUrl=" + allowUrl + ", secretkey=" + secretkey + ", authUrl=" + authUrl + ", checkTicketUrl=" + checkTicketUrl + ", sloUrl=" + sloUrl - + ", ssoLogoutCall=" + ssoLogoutCall + ", isHttp=" + isHttp + ", isSlo=" + isSlo + "]"; + + ", ssoLogoutCall=" + ssoLogoutCall + ", userinfoUrl=" + userinfoUrl + ", isHttp=" + isHttp + ", isSlo=" + isSlo + "]"; } @@ -232,7 +254,6 @@ public class SaSsoConfig implements Serializable { // -------------------- SaSsoHandle 所有回调函数 -------------------- - /** * SSO-Server端:未登录时返回的View */ @@ -244,12 +265,9 @@ public class SaSsoConfig implements Serializable { public BiFunction doLoginHandle = (name, pwd) -> SaResult.error(); /** - * SSO-Client端:Ticket无效时返回的View + * SSO-Client端:自定义校验Ticket返回值的处理逻辑 (每次从认证中心获取校验Ticket的结果后调用) */ - public Function ticketInvalidView = (ticket) -> { - // 此处向客户端提示ticket无效即可,不要重定向到SSO认证中心,否则容易引起无限重定向 - return "ticket无效: " + ticket; - }; + public BiFunction ticketResultHandle = null; /** * SSO-Client端:发送Http请求的处理函数 @@ -276,11 +294,11 @@ public class SaSsoConfig implements Serializable { } /** - * @param ticketInvalidView SSO-Client端:Ticket无效时返回的View + * @param SSO-Client端:自定义校验Ticket返回值的处理逻辑 (每次从认证中心获取校验Ticket的结果后调用) * @return 对象自身 */ - public SaSsoConfig setTicketInvalidView(Function ticketInvalidView) { - this.ticketInvalidView = ticketInvalidView; + public SaSsoConfig setTicketResultHandle(BiFunction ticketResultHandle) { + this.ticketResultHandle = ticketResultHandle; return this; } diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoHandle.java b/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoHandle.java index 6c20e82f..a45c2b92 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoHandle.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoHandle.java @@ -5,6 +5,7 @@ import cn.dev33.satoken.config.SaSsoConfig; import cn.dev33.satoken.context.SaHolder; import cn.dev33.satoken.context.model.SaRequest; import cn.dev33.satoken.context.model.SaResponse; +import cn.dev33.satoken.exception.SaTokenException; import cn.dev33.satoken.sso.SaSsoConsts.Api; import cn.dev33.satoken.sso.SaSsoConsts.ParamName; import cn.dev33.satoken.stp.StpLogic; @@ -24,7 +25,7 @@ public class SaSsoHandle { */ public static Object serverRequest() { - // 获取变量 + // 获取对象 SaRequest req = SaHolder.getRequest(); SaSsoConfig cfg = SaManager.getConfig().getSso(); @@ -59,7 +60,7 @@ public class SaSsoHandle { * @return 处理结果 */ public static Object ssoAuth() { - // 获取变量 + // 获取对象 SaRequest req = SaHolder.getRequest(); SaResponse res = SaHolder.getResponse(); SaSsoConfig cfg = SaManager.getConfig().getSso(); @@ -80,7 +81,7 @@ public class SaSsoHandle { * @return 处理结果 */ public static Object ssoDoLogin() { - // 获取变量 + // 获取对象 SaRequest req = SaHolder.getRequest(); SaSsoConfig cfg = SaManager.getConfig().getSso(); @@ -93,7 +94,7 @@ public class SaSsoHandle { * @return 处理结果 */ public static Object ssoCheckTicket() { - // 获取变量 + // 获取对象 SaRequest req = SaHolder.getRequest(); // 获取参数 @@ -115,7 +116,7 @@ public class SaSsoHandle { * @return 处理结果 */ public static Object ssoServerLogout() { - // 获取变量 + // 获取对象 SaRequest req = SaHolder.getRequest(); SaSsoConfig cfg = SaManager.getConfig().getSso(); StpLogic stpLogic = SaSsoUtil.saSsoTemplate.stpLogic; @@ -146,7 +147,7 @@ public class SaSsoHandle { */ public static Object clientRequest() { - // 获取变量 + // 获取对象 SaRequest req = SaHolder.getRequest(); SaSsoConfig cfg = SaManager.getConfig().getSso(); @@ -181,7 +182,7 @@ public class SaSsoHandle { * @return 处理结果 */ public static Object ssoLogin() { - // 获取变量 + // 获取对象 SaRequest req = SaHolder.getRequest(); SaResponse res = SaHolder.getResponse(); SaSsoConfig cfg = SaManager.getConfig().getSso(); @@ -219,13 +220,17 @@ public class SaSsoHandle { // 方式2:直连Redis校验ticket loginId = SaSsoUtil.checkTicket(ticket); } + // Be: 如果开发者自定义了处理逻辑 + if(cfg.ticketResultHandle != null) { + return cfg.ticketResultHandle.apply(loginId, back); + } // ------- 2、如果loginId有值,说明ticket有效,进行登录并重定向至back地址 if(loginId != null ) { stpLogic.login(loginId); return res.redirect(back); } else { // 如果ticket无效: - return cfg.ticketInvalidView.apply(ticket); + throw new SaTokenException("无效ticket:" + ticket); } } } @@ -235,7 +240,7 @@ public class SaSsoHandle { * @return 处理结果 */ public static Object ssoLogoutType2() { - // 获取变量 + // 获取对象 SaRequest req = SaHolder.getRequest(); SaResponse res = SaHolder.getResponse(); StpLogic stpLogic = SaSsoUtil.saSsoTemplate.stpLogic; @@ -254,7 +259,7 @@ public class SaSsoHandle { * @return 处理结果 */ public static Object ssoLogoutType3() { - // 获取变量 + // 获取对象 SaRequest req = SaHolder.getRequest(); SaResponse res = SaHolder.getResponse(); SaSsoConfig cfg = SaManager.getConfig().getSso(); @@ -283,7 +288,7 @@ public class SaSsoHandle { * @return 处理结果 */ public static Object ssoLogoutCall() { - // 获取变量 + // 获取对象 SaRequest req = SaHolder.getRequest(); StpLogic stpLogic = SaSsoUtil.saSsoTemplate.stpLogic; diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoTemplate.java b/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoTemplate.java index 50af22a3..d2236828 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoTemplate.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoTemplate.java @@ -248,6 +248,20 @@ public class SaSsoTemplate { return url; } + /** + * 构建URL:Server端 账号资料查询地址 + * @param loginId 账号id + * @return Server端 账号资料查询地址 + */ + public String buildUserinfoUrl(Object loginId) { + // 拼接 + String userinfoUrl = SaManager.getConfig().getSso().getUserinfoUrl(); + userinfoUrl = SaFoxUtil.joinParam(userinfoUrl, ParamName.loginId, loginId); + userinfoUrl = SaFoxUtil.joinParam(userinfoUrl, ParamName.secretkey, SaManager.getConfig().getSso().getSecretkey()); + // 返回 + return userinfoUrl; + } + // ------------------- SSO 模式三相关 ------------------- @@ -349,6 +363,16 @@ public class SaSsoTemplate { stpLogic.logoutByTokenValue(stpLogic.getTokenValueByLoginId(loginId)); } + /** + * 获取:账号资料 + * @param loginId 账号id + * @return 账号资料 + */ + public Object getUserinfo(Object loginId) { + String url = buildUserinfoUrl(loginId); + return SaManager.getConfig().getSso().sendHttp.apply(url); + } + // ------------------- 返回相应key ------------------- diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoUtil.java b/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoUtil.java index 5978c964..e71e86e6 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoUtil.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoUtil.java @@ -103,6 +103,14 @@ public class SaSsoUtil { saSsoTemplate.checkRedirectUrl(url); } + /** + * 构建URL:Server端 账号资料查询地址 + * @param loginId 账号id + * @return Server端 账号资料查询地址 + */ + public static String buildUserinfoUrl(Object loginId) { + return saSsoTemplate.buildUserinfoUrl(loginId); + } // ------------------- SSO 模式三 ------------------- @@ -161,4 +169,13 @@ public class SaSsoUtil { saSsoTemplate.singleLogout(secretkey, loginId, fun); } + /** + * 获取:账号资料 + * @param loginId 账号id + * @return 账号资料 + */ + public static Object getUserinfo(Object loginId) { + return saSsoTemplate.getUserinfo(loginId); + } + } diff --git a/sa-token-demo/sa-token-demo-sso2-client/src/main/java/com/pj/sso/SsoClientController.java b/sa-token-demo/sa-token-demo-sso2-client/src/main/java/com/pj/sso/SsoClientController.java index 9e2d3728..b2e9064a 100644 --- a/sa-token-demo/sa-token-demo-sso2-client/src/main/java/com/pj/sso/SsoClientController.java +++ b/sa-token-demo/sa-token-demo-sso2-client/src/main/java/com/pj/sso/SsoClientController.java @@ -1,10 +1,12 @@ package com.pj.sso; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import cn.dev33.satoken.sso.SaSsoHandle; import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaResult; /** * Sa-Token-SSO Client端 Controller @@ -30,4 +32,11 @@ public class SsoClientController { return SaSsoHandle.clientRequest(); } + // 全局异常拦截 + @ExceptionHandler + public SaResult handlerException(Exception e) { + e.printStackTrace(); + return SaResult.error(e.getMessage()); + } + } diff --git a/sa-token-demo/sa-token-demo-sso2-server/src/main/java/com/pj/sso/ExceptionHandle.java b/sa-token-demo/sa-token-demo-sso2-server/src/main/java/com/pj/sso/ExceptionHandle.java deleted file mode 100644 index 1f7dde78..00000000 --- a/sa-token-demo/sa-token-demo-sso2-server/src/main/java/com/pj/sso/ExceptionHandle.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.pj.sso; - -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -import cn.dev33.satoken.util.SaResult; - -/** - * 全局异常处理 - */ -@RestControllerAdvice -public class ExceptionHandle { - - // 全局异常拦截 - @ExceptionHandler - public SaResult handlerException(Exception e) { - e.printStackTrace(); - return SaResult.error(e.getMessage()); - } - -} diff --git a/sa-token-demo/sa-token-demo-sso2-server/src/main/java/com/pj/sso/SsoServerController.java b/sa-token-demo/sa-token-demo-sso2-server/src/main/java/com/pj/sso/SsoServerController.java index ec897b5c..d211abc2 100644 --- a/sa-token-demo/sa-token-demo-sso2-server/src/main/java/com/pj/sso/SsoServerController.java +++ b/sa-token-demo/sa-token-demo-sso2-server/src/main/java/com/pj/sso/SsoServerController.java @@ -1,6 +1,7 @@ package com.pj.sso; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.ModelAndView; @@ -43,5 +44,12 @@ public class SsoServerController { }) ; } + + // 全局异常拦截 + @ExceptionHandler + public SaResult handlerException(Exception e) { + e.printStackTrace(); + return SaResult.error(e.getMessage()); + } } diff --git a/sa-token-demo/sa-token-demo-sso3-client/src/main/java/com/pj/sso/SsoClientController.java b/sa-token-demo/sa-token-demo-sso3-client/src/main/java/com/pj/sso/SsoClientController.java index d47c1ada..3bd9da9e 100644 --- a/sa-token-demo/sa-token-demo-sso3-client/src/main/java/com/pj/sso/SsoClientController.java +++ b/sa-token-demo/sa-token-demo-sso3-client/src/main/java/com/pj/sso/SsoClientController.java @@ -1,6 +1,7 @@ package com.pj.sso; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -8,7 +9,9 @@ import com.ejlchina.okhttps.OkHttps; import cn.dev33.satoken.config.SaTokenConfig; import cn.dev33.satoken.sso.SaSsoHandle; +import cn.dev33.satoken.sso.SaSsoUtil; import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaResult; /** * Sa-Token-SSO Client端 Controller @@ -44,4 +47,19 @@ public class SsoClientController { ; } + // 查询我的账号信息 + @RequestMapping("/sso/myinfo") + public Object myinfo() { + Object userinfo = SaSsoUtil.getUserinfo(StpUtil.getLoginId()); + System.out.println("--------info:" + userinfo); + return userinfo; + } + + // 全局异常拦截 + @ExceptionHandler + public SaResult handlerException(Exception e) { + e.printStackTrace(); + return SaResult.error(e.getMessage()); + } + } diff --git a/sa-token-demo/sa-token-demo-sso3-client/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-sso3-client/src/main/resources/application.yml index 5c94b1a5..282d7db7 100644 --- a/sa-token-demo/sa-token-demo-sso3-client/src/main/resources/application.yml +++ b/sa-token-demo/sa-token-demo-sso3-client/src/main/resources/application.yml @@ -24,6 +24,8 @@ sa-token: slo-url: http://sa-sso-server.com:9000/sso/logout # 接口调用秘钥 secretkey: kQwIOrYvnXmSDkwEiFngrKidMcdrgKor + # SSO-Server端 查询userinfo地址 + userinfo-url: http://sa-sso-server.com:9000/sso/userinfo spring: # 配置Sa-Token单独使用的Redis连接 (此处需要和SSO-Server端连接同一个Redis) diff --git a/sa-token-demo/sa-token-demo-sso3-server/src/main/java/com/pj/sso/ExceptionHandle.java b/sa-token-demo/sa-token-demo-sso3-server/src/main/java/com/pj/sso/ExceptionHandle.java deleted file mode 100644 index 1f7dde78..00000000 --- a/sa-token-demo/sa-token-demo-sso3-server/src/main/java/com/pj/sso/ExceptionHandle.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.pj.sso; - -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -import cn.dev33.satoken.util.SaResult; - -/** - * 全局异常处理 - */ -@RestControllerAdvice -public class ExceptionHandle { - - // 全局异常拦截 - @ExceptionHandler - public SaResult handlerException(Exception e) { - e.printStackTrace(); - return SaResult.error(e.getMessage()); - } - -} diff --git a/sa-token-demo/sa-token-demo-sso3-server/src/main/java/com/pj/sso/SsoServerController.java b/sa-token-demo/sa-token-demo-sso3-server/src/main/java/com/pj/sso/SsoServerController.java index ef679a85..b6acac11 100644 --- a/sa-token-demo/sa-token-demo-sso3-server/src/main/java/com/pj/sso/SsoServerController.java +++ b/sa-token-demo/sa-token-demo-sso3-server/src/main/java/com/pj/sso/SsoServerController.java @@ -1,6 +1,7 @@ package com.pj.sso; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.ModelAndView; @@ -9,6 +10,7 @@ import com.ejlchina.okhttps.OkHttps; import cn.dev33.satoken.config.SaTokenConfig; import cn.dev33.satoken.sso.SaSsoHandle; +import cn.dev33.satoken.sso.SaSsoUtil; import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.util.SaResult; @@ -25,6 +27,22 @@ public class SsoServerController { public Object ssoRequest() { return SaSsoHandle.serverRequest(); } + + // 自定义接口:获取userinfo + @RequestMapping("/sso/userinfo") + public Object userinfo(String loginId, String secretkey) { + System.out.println("---------------- 获取userinfo --------"); + + // 校验调用秘钥 + SaSsoUtil.checkSecretkey(secretkey); + + // 自定义返回结果(模拟) + return SaResult.ok() + .set("id", loginId) + .set("name", "linxiaoyu") + .set("sex", "女") + .set("age", 18); + } // 配置SSO相关参数 @Autowired @@ -50,5 +68,12 @@ public class SsoServerController { }) ; } + + // 全局异常拦截 + @ExceptionHandler + public SaResult handlerException(Exception e) { + e.printStackTrace(); + return SaResult.error(e.getMessage()); + } } diff --git a/sa-token-doc/doc/sso/sso-type3.md b/sa-token-doc/doc/sso/sso-type3.md index 058c36fd..da518519 100644 --- a/sa-token-doc/doc/sso/sso-type3.md +++ b/sa-token-doc/doc/sso/sso-type3.md @@ -74,7 +74,53 @@ sa-token: > 注:如果已测试运行模式二,可先将Redis中的数据清空,以防旧数据对测试造成干扰 -### 2、无刷单点注销 +### 2、获取Userinfo +除了账号id,我们可能还需要将用户的昵称、头像等信息从 Server端 带到 Client端,即:用户资料的同步。要解决这个需求,我们只需: + +##### 2.1、在Server端自定义接口,查询用户资料 +``` java +// 自定义接口:获取userinfo +@RequestMapping("/sso/userinfo") +public Object userinfo(String loginId, String secretkey) { + System.out.println("---------------- 获取userinfo --------"); + + // 校验调用秘钥 + SaSsoUtil.checkSecretkey(secretkey); + + // 自定义返回结果(模拟) + return SaResult.ok() + .set("id", loginId) + .set("name", "linxiaoyu") + .set("sex", "女") + .set("age", 18); +} +``` + +##### 2.2、在Client端调用此接口查询userinfo +首先在yml中配置接口地址 +``` yml +sa-token: + sso: + # SSO-Server端 查询userinfo地址 + userinfo-url: http://sa-sso-server.com:9000/sso/userinfo +``` + +然后在`SsoClientController`中新增接口 +``` java +// 查询我的账号信息 +@RequestMapping("/sso/myinfo") +public Object myinfo() { + Object userinfo = SaSsoUtil.getUserinfo(StpUtil.getLoginId()); + System.out.println("--------info:" + userinfo); + return userinfo; +} +``` + +访问测试:[http://sa-sso-client2.com:9001/sso/myinfo](http://sa-sso-client2.com:9001/sso/myinfo) + + + +### 3、无刷单点注销 有了单点登录就必然要有单点注销,网上给出的大多数解决方案是将注销请求重定向至SSO-Server中心,逐个通知Client端下线 @@ -151,7 +197,7 @@ PS:这里我们为了方便演示,使用的是超链接跳页面的形式, -### 3、后记 +### 4、后记 当我们熟读三种模式的单点登录之后,其实不难发现:所谓单点登录,其本质就是多个系统之间的会话共享 当我们理解这一点之后,三种模式的工作原理也浮出水面: diff --git a/sa-token-doc/doc/use/config.md b/sa-token-doc/doc/use/config.md index 4de2f5a9..9c261645 100644 --- a/sa-token-doc/doc/use/config.md +++ b/sa-token-doc/doc/use/config.md @@ -97,17 +97,18 @@ PS:两者的区别在于:**`方式1会覆盖yml中的配置,方式2会与y ### 单点登录相关配置 -| 参数名称 | 类型 | 默认值 | 说明 | -| :-------- | :-------- | :-------- | :-------- | -| ticketTimeout | long | 300 | Ticket有效期 (单位: 秒) | -| allowUrl | String | * | 所有允许的授权回调地址,多个用逗号隔开 (不在此列表中的URL将禁止下放ticket),[详情请参考 SSO模式二的域名校验章节] | -| secretkey | String | null | 调用秘钥 (用于SSO模式三单点注销的接口通信身份校验) | -| authUrl | String | null | SSO-Server端 单点登录地址 | -| isHttp | Boolean | false | 是否使用http请求校验ticket值 | -| checkTicketUrl| String | null | SSO-Server端 Ticket校验地址 | -| isSlo | Boolean | false | 是否打开单点注销功能 | -| sloUrl | String | null | SSO-Server端 单点注销地址 | -| ssoLogoutCall | String | null | SSO-Client端 当前Client端的单点注销回调URL (为空时自动获取) | +| 参数名称 | 类型 | 默认值 | 所属端 | 说明 | +| :-------- | :-------- | :-------- | :-------- | :-------- | +| ticketTimeout | long | 300 | Server端 | Ticket有效期 (单位: 秒) | +| allowUrl | String | * | Server端 | 所有允许的授权回调地址,多个用逗号隔开 (不在此列表中的URL将禁止下放ticket),[详情请参考 SSO模式二的域名校验章节] | +| secretkey | String | null | Server端 & Client端 | 调用秘钥 (用于SSO模式三单点注销的接口通信身份校验) | +| authUrl | String | null | Client端 | SSO-Server端 单点登录地址 | +| isHttp | Boolean | false | Server端 & Client端 | 是否使用http请求校验ticket值 | +| checkTicketUrl| String | null | Client端 | SSO-Server端 Ticket校验地址 | +| isSlo | Boolean | false | Client端 | 是否打开单点注销功能 | +| sloUrl | String | null | Client端 | SSO-Server端 单点注销地址 | +| ssoLogoutCall | String | null | Client端 | SSO-Client端 当前Client端的单点注销回调URL (为空时自动获取) | +| userinfoUrl | String | null | Client端 | SSO-Server端 查询userinfo地址 | 配置示例: ``` yml