Confluence sso认证
背景
公司一直使用confluence来进行内部知识管理。老板突然想用飞书,然后让我将confluence与飞书打通。因此开始了解confluence和飞书的打通问题。
confluence sso 基础知识
Jira和Confluence集成了Atlassian自己开的一套SSO系统——Seraph。Seraph是由Atlassian开发的非常简单,可插入的J2EE 网页安全应用框架,它被广泛使用在Atlassian的产品中。
Seraph允许你写自定义的认证器,来将confluence/jira与你的系统来打通。
下图是Confluence认证的流程图,大体流程如下:
- 尝试通过request的passord和密码登录
- 尝试通过已经存在的session进行登录
- 尝试通过 cookie登录
- 尝试通过http ba认证登录
由于Authenticator.login(request, response, username, password, rememberMe)
这个方法出现了三次,看起来有点复杂。所以它已经被分解到了自己的子流程中。如下为登录的子流程:
支持的认证方法
如上述流程图所示,默认的Seraph认证支持四种认证方法:
- 请求参数。
os_username
和os_password
。 - session属性储存登录用户。
- cookie存储
username
和password
(remember me
登录) - 通过标准的http头进行Http ba认证
每个方法按上述流程图的顺序进行尝试。前面的方法成功登录后,会略过后续的登录流程。某个登录失败后,会依次尝试后续的方法直到所有的都失败。此时,用户被认为是“匿名用户”,并按Confluence中的匿名用户的权限进行处理。我们需要覆盖该方法,并在后面加上对应的与飞书的http认证就可以了。
参照源代码可以看出,Seraph支持基于角色的认证,但是这个在confluence中仅被用来鉴权 /admin/ URL的访问权限(如果要使用飞书的管理员,可以用这个)。
代码流程讲解
在系统中,上述的代码流程在com.atlassian.confluence.user.ConfluenceAuthenticator
中,我们如果需要自定义http认证,需要如下的流程:
- 写一个类,继承自
com.atlassian.confluence.user.ConfluenceAuthenticator
, 覆盖其getUser
方法, 参考代码seraph。(注意,示例中继承的类是DefaultAuthenticator
, 这个是在confluence 2.2及以下才可以,其余的请继承com.atlassian.confluence.user.ConfluenceAuthenticator
) - 将代码打包成jar放置于
confluence安装目录/WEB-INF/lib/
下(或者将类放入WEB-INF/classes/下,我没试过是否OK)。 - 打开
confluence安装目录/WEB-INF/classes/seraph-config.xml
, 修改如下内容:
<security-config>
<parameters>
<init-param>
<param-name>login.url</param-name>
<!--把登录url改为飞书的登录链接,appid填你的网页app的appid-->
<param-value>https://open.feishu.cn/open-apis/authen/v1/index?redirect_uri=${originalurl}&app_id=&state=</param-value>
</init-param>
<init-param>
<param-name>link.login.url</param-name>
<!--链接同上-->
<param-value>https://open.feishu.cn/open-apis/authen/v1/index?redirect_uri=${originalurl}&app_id=&state=</param-value>
</init-param>
<!-- 其它配置省略,不用动-->
</parameters>
<!-- 其它配置省略,不用动-->
<!--
修改认证器的class, 指向自己写的子类
<authenticator class="com.atlassian.confluence.user.ConfluenceAuthenticator"/>
-->
<authenticator class="com.example.test.xxConfluenceAuthenticator"/>
<!-- 其它配置省略 -->
</security-config>
- 保存,并重启confluence。登录后,系统会跳转到飞书登录页。
- 这种情况下,confluence的首页会变为飞书的登录页,我们可以通过飞书来登录了。但是还有个问题,confluence并不会关掉之前的用户名密码登录,用户还是可以访问那个页面。我们可以在nginx下加上对应的处理,来关掉这个页面的访问(apache自行按对应规则处理):
location /login.action {
// 钉钉,飞书等的登录跳回时,会带上code作为登录凭证,普通用户不会。因此直接将所有不带code访问login的请求rewrite
if ($args !~ code=){
rewrite ^ http://xx.com/;
}
}
总结
整体流程很简单,基本就是写个认证的子类,然后把配置中的类指向我们写的子类即可。麻烦的部分是如何构建一个confluence的开发测试环境,并且如何调用confluence的类,这一部分,下次再写吧。