SSO單點登錄,基本上是做門戶系統(tǒng)的必備工作之一。當我們用Liferay的時候,缺省已經(jīng)集成了CAS、OpenID、LDAP、NTLM、OpenSSO等單點登錄的解決方案。
但這些集成方案都有一個小問題,就是不能把用戶管理跟Liferay自身的用戶管理集成起來。也就是說,我們必須要另外有一個用戶管理的解決方案。盡管使用LDAP可能是更流行的解決方案,但畢竟還是增大了我們的工作量,有沒有就使用Liferay自身的用戶管理的SSO集成方案?
本文就是試圖來解決這個問題,主要基于以下幾點來實現(xiàn)SSO。
-
使用Liferay的用戶注冊、管理作為統(tǒng)一用戶的基礎(chǔ)。
-
使用CAS作為單點登錄的服務器端和客戶端實現(xiàn)。
-
對Liferay做必要的定制,滿足SSO客戶端產(chǎn)品的要求。
CAS的定制
下載的CAS Server,包括Liferay集成的CAS Server,都是只提供一個演示的登錄驗證,只要輸入賬號和密碼相同就可登錄成功。
我們使用Liferay的身份認證,需要做的第一件事情就是定制這個登錄實現(xiàn)。
實現(xiàn)賬號密碼驗證的代碼
在CAS中,我們新寫一個Java文件,com.liferay.sso.cas.adaptors.LiferayAuthenticationHandler,繼承AbstractUsernamePasswordAuthenticationHandler。
在這個類中,使用JDBC連接Liferay的數(shù)據(jù)庫,實現(xiàn)賬號和密碼的驗證。其中,賬號使用Liferay中的screenName。
由于在Liferay中,不同的Company可能會有相同的screenName,因此這種實現(xiàn)方法會有一些限制。最簡單的做法,就是Liferay中只配置一個Company。
修改CAS配置文件
修改CAS的配置文件WEB-INF/deployerConfigContext.xml,修改<property name="authenticationHandlers">的內(nèi)容。我的代碼為:
<property name="authenticationHandlers">
<list>
<bean
class="org.jasig.cas.authentication.handler.support.
HttpBasedServiceCredentialsAuthenticationHandler"/>
<bean
class="com.liferay.sso.cas.adaptors.LiferayAuthenticationHandler">
<property name="dataSource" ref="liferayDbcpDataSource"/>
</bean>
</list>
</property>
當然還需要一些配置數(shù)據(jù)庫的代碼,自行實現(xiàn)即可。
經(jīng)過這兩步,重新啟動就可以用Liferay的賬號和密碼進行認證了。
Liferay的定制
作為用戶的集中管理,Liferay還應該提供給客戶端應用,能夠很方便的得到用戶的詳細信息,CAS本身是不解決這個問題的。
一個比較簡單的做法,就是在Liferay中實現(xiàn)一個Servlet,根據(jù)用戶screenName,得到用戶的詳細信息。數(shù)據(jù)格式,為了適應不同的客戶端應用,可以采用XML進行編碼。
Cas客戶端的定制
CAS自己提供的Client,已經(jīng)能滿足用戶認證的功能。我們需要進一步定制的,是解決Auto Login和新用戶創(chuàng)建的問題。這兩點,需要在每個集成CAS的客戶端應用中實現(xiàn)。
Auto Login,可以借鑒Liferay自己的一些CasAutoLogin,根據(jù)已登錄的Cas用戶,初始化客戶端應用所需要的一些Session信息。
CAS中還有一個重要的問題,就是當CAS的用戶在客戶端不存在的時候,怎么解決。還有一個更嚴重的問題,如果客戶端已經(jīng)有了用戶,這時候怎么實現(xiàn)Liferay用戶同本地用戶的映射?
Liferay用戶同本地用戶的映射問題
用戶映射,根據(jù)不同的系統(tǒng),或者不同的用戶需求應該有不同的實現(xiàn)方案。
使用相同的用戶名
這是比較簡單的做法,直接使用相同的用戶名就行。當SSO的用戶在本地應用中不存在的時候,可以有兩種解決方法:
-
允許用戶映射本地已經(jīng)存在的一個用戶:讓用戶輸入一個賬號密碼,驗證其本地合法用戶的身份,然后自動將本地用戶名修改為SSO相同的用戶名。如果在本地還沒有賬戶,可以直接使用第二種方案創(chuàng)建新用戶。
-
直接創(chuàng)建新的本地用戶:調(diào)用Liferay的獲取用戶的接口,獲取用戶的詳細信息,然后直接調(diào)用本地注冊新用戶的代碼,創(chuàng)建一個本地新用戶。
這兩種情況下,下次用戶登錄時,直接根據(jù)相同用戶名進行用戶映射即可。
客戶端應用自己保存用戶映射
如果客戶端應用不修改本地用戶的用戶名,可以添加代碼,在本地實現(xiàn)一個用戶的映射機制。比如將SSO的user1,映射為客戶端的用戶user2。
當然這種實現(xiàn),也需要提供一個本地的用戶驗證機制,實現(xiàn)用戶的正確映射。
在Liferay中添加用戶映射的機制
考慮到有很多產(chǎn)品需要集成,如果每個產(chǎn)品都去實現(xiàn)用戶映射,工作量比較大,可以考慮到Liferay中實現(xiàn)一個統(tǒng)一的映射機制。
這種實現(xiàn),也需要提供一個本地的用戶驗證機制,實現(xiàn)用戶的正確映射。
這時候,需要做的工作有幾部分:
-
新建一個數(shù)據(jù)表,用以保存SSO用戶和各個產(chǎn)品的用戶之間的映射機制。
-
在Liferay中定制的獲取用戶信息的接口中,添加用戶映射的信息。這樣,SSO客戶端讀取用戶信息時,能夠直接讀取到用戶在本地的用戶名。
-
Liferay中添加一個接口,由客戶端調(diào)用,用于保存用戶映射信息