单点登录是企业应用不可回避的问题,下面介绍一下 BroFramework 中如何与外部系统进行SSO集成。
一般来说,SSO按照发起方可分为入站SSO(又称反向SSO,inbound sso)和出站SSO(outbound sso)。顾名思义,一个系统的入站SSO就是登录到其他系统(如门户)后,再单点登录到本系统;而出站SSO就是登录到本系统后,再单点登录到其他的系统。
BroFramework 提供了一个默认的集成规范模板,外部系统可以参照该规范进行集成,而在基于 BroFWK 的系统中,只需要进行简单配置即可。
集成规范说明如下:
- 通过外部系统(集成方)访问 BroFWK 系统时,在请求链接中带上如下参数:
- appid: 必须。外部系统的名称或编码
- token: 必须。外部系统定义的一个加密字符串,一般有有效期限制(常见的是5分钟)
- username: 可选。当前用户,用于校验。
- 例如:http://bropen.host:port/context/foo/bar?appid=portal&username=zhangsan&token=.....
- BroFWK 系统捕获到上述形式的 URL 后,将 token 拼到一个双方约定好的外部系统的 URL 中,并进行回调,如:
- URL为 http://thirdapp.host:port/context/sso?token=
则回调URL为:....?token=.... - URL 为 http://thirdapp.host:port/context/sso
则回调URL为:....sso?token=.... - 此外,如果第三方系统是JavaEE的,并且支持将url重写方式传递jsessionid,即URL形如:http://thirdapp.host:port/context/sso;jsessionid=
则回调URL为: .../sso;jsessionid=xxxxx
- 外部系统解析回调 URL 中的 token,返回一个包含用户名的文本字符串
例如:zhangsan - BroFWK 系统获得回调返回的文本串后,和之前 URL 中的 username(如果有的话) 进行比较,如果一样,则认为步骤1中的访问合法,完成单点登录的功能
当外部系统使用本规范来进行集成时,对于基于 BroFWK 的系统,可以在工程的 BrootStrap 中,添加如下配置代码即可(测试时也可以直接在console里配置):
import bropen.framework.core.security.AuthenticationUtils;
AuthenticationUtils.enableCommonSSO( appid , url );
当通过外部系统访问本系统时,日志中会输出:
[INFO bropen.framework.core.security.AuthenticationFilter] - 用户appid SSO成功:zhangsan
如果外部系统无法参照上面的集成规范来开发,可以在本系统中二次开发自定义拦截器来实现入站SSO。
不过,不同于传统的 Filter,这里的 SSO 拦截器的开发极其精简,只是一个带有几个闭包的 Map,接口与示例如下:
import bropen.framework.core.security.AuthenticationUtils;
AuthenticationUtils.addSSOInterceptors([
// 名称(必须)
name: "Sample",
// 优先级(可选):默认都为100,数字越大表示优先级越低(执行顺序靠后);
// 一般建议通过url传参的优先级提前(如rtx),而通过cookie传token的优先级靠后(如ltpa)
priority: 100,
// 是否可以被后面的拦截器覆盖(可选):如拦截器A先执行,返回用户a,但可被覆盖;继续执行拦截器B,返回用户b,则将用b进行sso
overwritable: false,
// SSO接口(可选):返回用户名则表示sso成功,或者返回一个map包含用户名和重定向的URL
before: { request, response ->
return request.getParameter("username");
return [username: request.getParameter("god"), redirect: request.getParameter("redirect")]
},
// SSO成功、并创建用户session后的事件(可选),可以处理处理善后,如设置一些额外的 cookie 或者 session 等
after: { request, response, username->
},
// 登录成功后执行的事件(可选),在after之前执行;此外,如果仅仅想要在用户登录后做些事情,可以设置一个不包含before、after的拦截器
login: { request, response, username ->
},
// 用户点注销时执行的事件(可选),可以用来处理联合注销(同时注销掉其他系统)
logout: { request, response ->
}
])
注1:调试过程中,可以在 console 中随意修改调试,测试通过后,再将其写到工程的 BootStrap 或者某个 Service 的 bootStrapInit 方法中。
注2:在访问控制(Requestmap)中设置为允许匿名访问的 URI 不会经过拦截器
除了上述配置与自定义开发外,BroFWK 中已经实现并内置了几种SSO:
- GOD:仅开发环境下生效。
将用户名拼到 URL 的 god 参数中,即可实现单点登录,如:http://host:port/context/foo/bar?god=zhangsan - INTERNAL:使用相同数据源的多个应用之间的SSO。
比如某个项目中,由于需求比较多,开发了 app1、app2... 等多个web工程,这些工程共用一个数据库,则登录到任意一个app后,切换到其他app时可以实现单点登录 - LTPA:和 IBM 相关产品(如Portal、Domino等)集成。
比如和 WebSphere Portal 进行单点登录时,只需要在系统配置中设置如下几个参数即可实现从Portal到应用的SSO:- bropen.framework.security.sso.ltpa.password:即 LTPA Key 的密码
- bropen.framework.security.sso.ltpa.3DESKey:即 LTPA Key 文件中的 com.ibm.websphere.ltpa.3DESKey
- RTX:和腾讯RTX集成
当RTX服务器上配置了SDK权限、并且部署了相应的BROPEN SSO包后,只需要在基于 BroFWK 的系统配置中设置如下几个参数,即可实现从 RTX 客户端到应用的SSO:- bropen.framework.plugin.im.rtx.enabled:启用 rtx 集成
- bropen.framework.plugin.im.rtx.sdk.url:设置 rtx sdk 的URL,如 http://rtx.bropen.com.cn:8012/
- Archive:内部归档
启用归档功能后,用于抓取文档的SSO,仅限系统内部使用。
当基于 BroFWK 的系统与外部系统做出站SSO集成时,集成方案和入站SSO的集成模板类似:
- 在本系统中生成如下链接:
http://bropen.host:port/context/sso/remote?url=http://thirdapp.host:port/foo&redirect=/...&type=xml- 其中 url 为需要访问的外部系统的URL地址。
- 如果外部系统不支持使用拦截器来实现SSO,而必须先通过某个URL来实现SSO,然后再重定向到目标URI的话,则url配置为实现SSO的外部系统地址、然后配置redirect参数为实际需要访问的外部系统地址(如打开一个待办)
- 其中 type 为外部系统回调获得用户信息时的数据类型,默认为xml,还可以是 text(仅返回用户名)、json
- 点击上面的链接后,浏览器自动重定向到 url 参数指向的地址(外部系统),并且带上如下额外的参数
- JSESSIONID:当前用户的session id
- callback:供外部系统回调、以获得用户信息的URL
- redirect:等同于上面的 redirect 参数,由外部系统处理(SSO成功后的重定向)
- 浏览器重定向到外部系统后,外部系统需要回调参数 callback 中的URL以获得用户信息;
回调时,需要将参数 JSESSIONID 的值放到同名 cookie 中,
或者拼到 callback 参数值后(不太安全),如:http://bropen.host:port/context/sso?type=text;jsessionid=xxxx。 - 当外部系统回调 callback url 时,本系统会返回参数 type 指定的数据:
- text:只是返回用户名,如 zhangsan
- json:返回json格式封装的用户信息,如:
{
"session":{
"id":"F43522E0A4E486B0436AC139A7869066",
"createTime":1386644060862
},
"user":{
"id":31,
"name":"zhangsan",
"nickname":"张三"
},
"employee":{
"id":30,
"name":"张三",
"email":"zhangsan@bropen.com.cn",
"code":"6519"
},
"organization":{
"id":7,
"name":"项目部",
"fullName":"博瑞开源/项目部"
}
} - xml(默认):返回xml格式封装的用户信息,如:
<sso>
<session id="F43522E0A4E486B0436AC139A7869066" creation_time="1386644060862"></session>
<user id="31" name="zhangsan" nickname="张三"></user>
<employee id="30" name="张三" email="zhangsan@chec.com.cn" code="6519"></employee>
<organization id="7" name="项目部" full_name="博瑞开源/项目部"></organization>
</sso>
- 当外部系统获得用户信息后,就可以自行实现SSO了;此外,如果参数中包含 redirect,则重定向到对应的URL。
同入站 SSO 一样,BroFWK 中已经实现并内置了几种可选的SSO组件,当然对应的应用系统中需要做一些简单的部署工作:
- IBM WebSphere Portal:
作为一个通用组件,除了 BroFWK 外,其他系统也可以通过该组件和 WebSphere Portal 做反向SSO,如RTX
- Discuz 论坛:
在 Discuz 上部署后,还可支持自动创建用户 - 腾讯 RTX:
在 RTX 上部署后,除基于 BroFWK 的系统和Portal外,还可支持任何应用(需二次开发)到RTX 客户端的出站SSO