目录
[显示]

1.背景

前一阵部门要做一个内部讨论区,希望能和原有的gitlab集成在一起。

discuz虽然成熟但是感觉不够高大上,找了几个ruby的论坛discourse,rabel虽然时髦值够了但是成熟度又缺了点,最后选了php的question2answer作为论坛程序,采用iframe的方式嵌入原来的gitlab程序。

2.单点登录方案

2.1.共享cookie

  • 在cookie里保存user的信息,php读cookie并取得用户信息。
  • ruby和php程序要在同一个域名
  • cookie在客户端是可见的,一般要对cookie进行加密。
  • 数据不安全

2.2.共享session

  • 在cookie里保存ruby session信息,php获得session信息后读session数据。
  • ruby和php程序要在同一个域名
  • session内容客户端不可见。

2.3.cas

  • 通过统一认证服务登录
  • ruby和php登录时重定向至认证服务器,通过验证后回调相应服务保存token,之后只要具体服务向cas请求token是否过期就可以判断是否登录。

由于两个业务在同一个域名下,这里就放弃了复杂的cas方案;考虑源代码安全,没有用cookie存储用户信息,最后决定使用共享session的方式实现单点登录

3.通过session单点登录

3.1.rails与session

gitlab使用devise作为登录框架,关于session的配置在config/initilizers/sessions.rb下,默认使用redis方式保存session

这里也可以改成在数据库或者memcached里存储,存储格式与redis类似,不多讲了。

redis里key为session id,value为序列化后的数据,默认使用的序列化算法为marshal,理论上只要php读出内容来就可以取得session数据了。

3.2.ruby与序列化

不幸的是,php里没有能够直接反序列化marshal对象的的方法。

最初考虑把marshal改为json方式存储,需要修改redis-store的一些代码,主要是覆盖源代码中的marshal和unmarshal函数,替换为json实现。具体可以参考:Sharing Rails sessions with PHP, ColdFusion, and more!

不过用这个方法出现了一些问题:marshal序列话会保存对象的一些meta信息,json是没有这些信息的,导致反序列化之后的ruby对象与序列化之前不一样。

在网上搜索很久,一个日文的blog提出了解决方案:Rails sessionのシリアライズにJSONが使われない理由: なぜMarshal? JSON/YAMLの罠

主要是在反序列化的时候加了这么一句:

3.3.折衷的方式

这么深度的修改对于这个需求似乎太复杂了,最后还是决定用简单些的方式,利用ruby开放一个session的json接口,php通过调用接口获得用户信息,修改的地方很少:

ruby

php