文章《體驗(yàn)WebLogic Server 8.1 SP4新增功能之WebLogic Single Sign-On》(http://dev2dev.bea.com.cn/techdoc/200507499.html)中介紹了使用WLS8.1 SP4版本中的Single Pass Negotiate Identity Assertion Provider完成與Windows平臺(tái)的SSO。但有更多的人可能希望在不借助,或者不與Windows集成的情況下完成Single Sign-On。Kerberos當(dāng)然可以是其中的一種解決辦法,但是目前互聯(lián)網(wǎng)上應(yīng)用更多的是SAML,一個(gè)用于在網(wǎng)絡(luò)實(shí)體間交換安全認(rèn)證信息的基于XML的框架。
本文據(jù)此提出一種適用(針對(duì))于WebLogic Server的,簡(jiǎn)單、可行的SSO解決方案。這個(gè)方案以集中統(tǒng)一的用戶信息為基礎(chǔ),但不包括通常理解的權(quán)限管理,而僅僅提供一個(gè)身份驗(yàn)證的服務(wù)。因?yàn)橐话闱闆r下,一個(gè)企業(yè)內(nèi)部的多個(gè)成熟系統(tǒng)通常分別有自己的已經(jīng)比較完善的用戶身份驗(yàn)證和權(quán)限管理功能。在這種情況下,為整合多個(gè)業(yè)務(wù)系統(tǒng)而提供包括權(quán)限管理在內(nèi)的多種安全服務(wù),常常將問(wèn)題復(fù)雜化(盡管SAML可以做到這一點(diǎn))。
因此本文提出的方案將只解決用戶的身份驗(yàn)證,即實(shí)現(xiàn)SSO的本義。在SSO幫助用戶完成身份驗(yàn)證后,由各個(gè)業(yè)務(wù)系統(tǒng)本身的權(quán)限管理進(jìn)行用戶行為的進(jìn)一步控制。這樣不僅完成了用戶賬號(hào)的集中管理(SAML可以完成不同系統(tǒng)間不同賬號(hào)的federated但不在本文討論范圍內(nèi)),又不失原有系統(tǒng)靈活的權(quán)限控制。而且方案簡(jiǎn)單可行,不需要對(duì)原有應(yīng)用做較大更改,適合快速解決Single Sign-On問(wèn)題。
如果有更復(fù)雜的需求,完全可以在本文的基礎(chǔ)上,參考Shibboleth(http://shibboleth.internet2.edu/)項(xiàng)目以及SourceID(http://www.sourceid.org/index.html)的項(xiàng)目進(jìn)行深入的研究和了解,以找出最適合自己的解決方案。
名詞
SAML
本文將以SAML 1.1實(shí)現(xiàn)SSO。SAML定義了一個(gè)用于在線商業(yè)系統(tǒng)間交換安全信息的基于XML的框架,它由OASIS (the Organization for the Advancement of Structured Information Standards)組織的Security Services Technical Committee (SSTC)開發(fā)。詳情參考文章后面的參考資料部分。
OpenSAML
一個(gè)開源的SAML1.1實(shí)現(xiàn),本文使用opensaml1.1完成與SAML相關(guān)的邏輯處理。OpenSAML是Shibboleth項(xiàng)目的一部分。Shibboleth是一個(gè)針對(duì)SSO的開源項(xiàng)目。
WebLogic Server
業(yè)界領(lǐng)先的J2EE應(yīng)用服務(wù)器。本文的方案以WebLogic Server 8.1SP4為基礎(chǔ)。本文附帶的Demo應(yīng)用只能跑在WLS8.1 SP4上,如果8.1SP3等版本需要適當(dāng)改動(dòng)。
Identity Assertion Provider
Identity Assertion Provider是WebLogic 7以后提供的眾多Provider的一種,它其實(shí)就是一個(gè)Authentication Provider,只不過(guò)它不需要口令來(lái)完成用戶的身份驗(yàn)證;如果在其他平臺(tái)比如Tomcat上實(shí)現(xiàn),也可以是一個(gè)普通的LoginModule,只需要通過(guò)CallbackHandler獲取Token然后驗(yàn)證就可以了。
本文附帶一個(gè)示例的Identity Assertion Provider。
Java KeyStore
本文將附帶一個(gè)自簽名的java key store,它由JDK帶的Keytool生成并簽名。
Service Provide
服務(wù)提供者。就是我們一般理解的業(yè)務(wù)系統(tǒng),它通過(guò)配置在其上的Identity Assertion Provider完成對(duì)用戶提交Token的校驗(yàn),一般又稱為SAML Assertion Consumer。文章后面簡(jiǎn)稱為SP。
Identity Provider
身份認(rèn)證提供者。通過(guò)它對(duì)用戶進(jìn)行身份驗(yàn)證,以及生成SAML Assertion Token,又稱為SAML Assertion Productor。本方案的實(shí)現(xiàn)中核心為一個(gè)Servlet。文章后面簡(jiǎn)稱為IDP。
Use Case
本文描述的方案實(shí)現(xiàn)了SAML 1.1 提供的POST Profile User Case,并有適當(dāng)修改。
技術(shù)實(shí)現(xiàn)
這里描述一下前面Use Case中涉及的幾個(gè)技術(shù)方面。
<filter-mapping>
<filter-name>SAMLAuthFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
這里表示SP全部的頁(yè)面受SAMLAuthFilter保護(hù)。
我們使用 WebLogic提供的 API進(jìn)行用戶身份驗(yàn)證,這樣才能完成一個(gè)讓 WebLogic Server認(rèn)為是合法的登錄。這個(gè)weblogic.servlet.security.ServletAuthentication提供的方法具體實(shí)現(xiàn)在不同的SP版本中總有變化,比如WLS8.1 SP3和8.1 SP4,因此需要留意這一點(diǎn)。本文方案的實(shí)現(xiàn),以WELS8.1SP4為準(zhǔn)。
public static int login(java.lang.String username,
java.lang.String password,
javax.servlet.http.HttpServletRequest request)
throws javax.security.auth.login.LoginException
Returns an int value for AUTHENTICATED or FAILED_AUTHENTICATION after using the username and password to authenticate the user and setting that user information into the session. This method is similar to "weak", except that the LoginException is propogated to caller.
Parameters:
username - String
password - String
request - HttpServletRequest
Returns:
int authentication value
Throws:
javax.security.auth.login.LoginException -
這里的代碼來(lái)自于opensaml提供的POSTProfileTest.java,用于生成 SAMLResponse并進(jìn)行簽名
SAMLResponse r = SAMLPOSTProfile.prepare(
"www.opensaml.org",
"www.opensaml.org",
Collections.singleton("http://www.opensaml.org"),
"foo",
"foo",
null,
"127.0.0.1",
"foo",
new Date(),
Collections.singleton(
new SAMLAuthorityBinding(SAMLBinding.SAML_SOAP_HTTPS,
"http://www.opensaml.org",
new QName(XML.SAMLP_NS,"AttributeQuery")
)
)
);
assertNotNull("No SAMLResponse was generated.",r);
Iterator i = r.getAssertions();
((SAMLAssertion)i.next()).sign(
XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1,
ks.getKey(alias,password),
Arrays.asList(ks.getCertificateChain(alias))
);
r.sign(
XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1,
ks.getKey(alias,password),
Arrays.asList(ks.getCertificateChain(alias))
);
具體Identity Assertion Provider的實(shí)現(xiàn)超出了本文討論的篇幅。這里只描述其需要實(shí)現(xiàn)的主要邏輯,同樣來(lái)自于POSTProfileTest.java
assertTrue("SAMLResponse is not signed.",r.isSigned());
System.err.println("================ Generated Response ===============");
r.toStream(System.err);
System.err.println();
r.verify(ks.getCertificate(alias));
SAMLResponse r2 = SAMLPOSTProfile.accept(r.toBase64(), "www.opensaml.org", 60, true);
assertTrue("SAMLResponse is not signed.",r2.isSigned());
SAMLPOSTProfile.getSSOAssertion(r2,Collections.singleton("http://www.opensaml.org")).verify(ks.getCertificate(alias));
r2.verify(ks.getCertificate(alias));
System.err.println("================ Verified Response ===============");
r2.toStream(System.err);
System.err.println();
只要將上面的邏輯放入在Identity Assertion Provider中就可以了。
在IDP響應(yīng)給用戶的頁(yè)面包含了一個(gè)自動(dòng)提交的表單,將SAML Assertion Token通過(guò)HTTP POST提交給用戶請(qǐng)求的SP頁(yè)面。這部分由SAML1.1中的Browser/POST Profile定義。由于生成的SAML Assertion往往比較大,不能通過(guò)HTTP GET提交,因此通過(guò)自動(dòng)提交表單完成。這樣用戶仍然可能會(huì)感受到短暫的跳轉(zhuǎn),如果使用Browser/Artifact Profile,那么將由SP和IDP進(jìn)行溝通,用戶感受會(huì)好一點(diǎn),但是開發(fā),部署均麻煩一些,SP和IDP需要雙向SSL,并且opensaml沒(méi)有提供這個(gè)實(shí)現(xiàn),這里就不深入討論了。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title>Auto Submit</title>
</head>
<body onLoad="document.myform.submit()">
<form name="myform" action="">
</form>
</body>
</html>
綜上,大家看是不是很簡(jiǎn)單呢?J
Demo的部署和演示
這里介紹附帶的幾個(gè)文件
sp.war
Service Provider應(yīng)用,可以直接部署在WebLogic Server上。
idp.war
Identity Provider應(yīng)用??梢灾苯硬渴鹪赪ebLogic Server上。其中主要就是一個(gè)LogonServlet
samlIdentityProvider.jar
這里提供的SAML Identity Assertion Provider只是為了演示使用,如果需要應(yīng)用在具體的生產(chǎn)環(huán)境中,則需要詳盡的測(cè)試,調(diào)優(yōu),以及適當(dāng)?shù)男薷摹?/p>
opensaml.jar
運(yùn)行OpenSAML需要的jar包,同時(shí)它使用了很多第三方的類庫(kù),因此這些第三方的jar包也需要,由于文件太大,不在附件中,大家可以去www.opensaml.org下載最新版本。
xbean.jar
包含在WLS8 /server/lib目錄下,需要在啟動(dòng)WLS的腳本中加入到classpath中
endorsed
OpenSAML要求使用的XML Parser,在附件中
idp.jks
使用keytool生成的KeyStore,存放了一對(duì)密鑰
idp.cer
密鑰對(duì)中的公鑰,SP使用它校驗(yàn)Token是否有效
下面介紹Demo的部署過(guò)程。
至此,部署成功。
下面是演示過(guò)程:
演示一:
演示二:
演示三(圖片省略):
如果IDP網(wǎng)站當(dāng)機(jī),那么只是喪失SSO而已,不會(huì)影響業(yè)務(wù)系統(tǒng)的使用,這一點(diǎn)對(duì)大的應(yīng)用來(lái)說(shuō)很重要。
參考資料
聯(lián)系客服