保持 Project Zero 和 WebSphere sMash 应用程序的安全性,第 3 部分: 用 OpenID 保护 Project Zero 应用程序
2009-10-28 00:00:00 来源:WEB开发网 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閻愵剙鍔ょ紓宥咃躬瀵鎮㈤崗灏栨嫽闁诲酣娼ф竟濠偽i鍓х<闁绘劦鍓欓崝銈囩磽瀹ュ拑韬€殿喖顭烽幃銏ゅ礂鐏忔牗瀚介梺璇查叄濞佳勭珶婵犲伣锝夘敊閸撗咃紲闂佺粯鍔﹂崜娆撳礉閵堝洨纾界€广儱鎷戦煬顒傗偓娈垮枛椤兘骞冮姀銈呯閻忓繑鐗楃€氫粙姊虹拠鏌ュ弰婵炰匠鍕彾濠电姴浼i敐澶樻晩闁告挆鍜冪床闂備胶绮崝锕傚礈濞嗘挸绀夐柕鍫濇川绾剧晫鈧箍鍎遍幏鎴︾叕椤掑倵鍋撳▓鍨灈妞ゎ厾鍏橀獮鍐閵堝懐顦ч柣蹇撶箲閻楁鈧矮绮欏铏规嫚閺屻儱寮板┑鐐板尃閸曨厾褰炬繝鐢靛Т娴硷綁鏁愭径妯绘櫓闂佸憡鎸嗛崪鍐簥闂傚倷娴囬鏍垂鎼淬劌绀冮柨婵嗘閻﹂亶姊婚崒娆掑厡妞ゃ垹锕ら埢宥夊即閵忕姷顔夐梺鎼炲労閸撴瑩鎮橀幎鑺ョ厸闁告劑鍔庢晶鏇犵磼閳ь剟宕橀埞澶哥盎闂婎偄娲ゅù鐑剿囬敃鈧湁婵犲﹤鐗忛悾娲煛鐏炶濡奸柍瑙勫灴瀹曞崬鈻庤箛鎾寸槗缂傚倸鍊烽梽宥夊礉鎼达絽鍨濇い鏍仜妗呴梺鍛婃处閸ㄦ壆绮婚幎鑺ュ€甸柨婵嗙凹缁ㄨ棄霉閻樿崵鐣烘慨濠冩そ濡啫鈽夊▎鎰€烽梺璇插閻噣宕¢幎鑺ュ仒妞ゆ洍鍋撶€规洖鐖奸、妤佸緞鐎n偅鐝┑鐘愁問閸n垳寰婇崜褉鍋撶粭娑樻搐缁犳煡鏌涢妷顔煎闁藉啰鍠栭弻锝夊棘閹稿孩鍠愰梺鑽ゅ枎缂嶅﹪寮诲☉鈶┾偓锕傚箣濠靛洨浜俊鐐€ら崜娆撴偋閸℃稈鈧棃宕橀鍢壯囧箹缁厜鍋撻懠顒€鍤紓鍌氬€风欢锟犲窗濡ゅ懎绠伴柟闂寸劍閸嬧晠鏌i幋锝嗩棄缁绢厸鍋撻梻浣虹帛閸旀洜绮旈棃娴虫盯宕橀鍏兼К闂侀€炲苯澧柕鍥у楠炴帡骞嬪┑鎰磻闁诲氦顫夐幐椋庣矆娓氣偓閸╃偤骞嬮敂钘変汗闂佸湱绮敮鈺傚閳ь剛绱撴担鐟板姢鐟滄壆鍋熼崚鎺戔枎閹惧疇鎽曞┑鐐村灦閻喖鈻介鍫熺厵閻熸瑥瀚慨鍥ㄣ亜閵夛妇绠炴慨濠冩そ閺屽懘鎮欓懠璺侯伃婵犫拃鍌氬祮闁哄瞼鍠栭幖褰掝敃閿濆懐锛撻梻浣瑰缁诲嫰宕戝☉銏犵厴闁瑰濮崑鎾绘晲鎼存ê浜炬い鎾寸⊕濞呭﹪鏌$仦鐣屝f繛纰变邯楠炲繒浠﹂挊澶婅厫闂傚倷鐒﹂惇褰掑磹閺囥垹绠犻柟閭﹀枟椤洟鏌熼幆褏鎽犲┑顖涙尦閺屾盯骞橀弶鎴犵シ闂佸憡鎸稿畷顒勨€旈崘顔嘉ч柛鈩冾殘娴犳悂姊洪懡銈呮毐闁哄懏鐩幃楣冩倻閽樺)銊ф喐婢舵劕纾婚柟鍓х帛閺呮煡骞栫划鐟板⒉闁诲繐绉瑰铏圭磼濡闉嶅┑鐐插级閿曘垺淇婇悽绋跨妞ゆ牗姘ㄩ悿鈧梻鍌氬€搁悧濠勭矙閹邦喛濮抽柤娴嬫櫇绾捐棄霉閿濆牊顥夐柣鎾村姈閹便劌螣缁嬪灝顬嬪┑鈥冲级閸旀瑩鐛Ο鍏煎珰闁肩⒈鍓﹀Σ浼存⒒娴gǹ鏆遍柟纰卞亰瀹曟劖绻濆В绋挎喘瀵埖鎯旈幘瀛樻澑婵$偑鍊栧濠氬Υ鐎n亶鍟呴柕澶涜礋娴滄粍銇勯幘璺轰粶婵℃彃顭烽弻锝夋晲閸パ冨箣濡ょ姷鍋炵敮锟犵嵁鐎n喖绫嶉柍褜鍓熼幃妤佺節濮橆厸鎷洪柣鐔哥懃鐎氼參宕曞Δ鍛厱婵☆垵銆€閸嬫捇鎮㈤幓鎺戠阀濠电姷鏁告慨鐑藉极閸涘﹥鍙忛柣鎴f閺嬩線鏌涘☉姗堟敾闁告瑥绻戦妵鍕箻閸楃偟浠肩紒鐐劤椤兘寮婚悢鐓庣鐟滃繒鏁☉銏$厓闂佸灝顑呴悘锕傛煏閸パ冾伃妤犵偞甯″畷鍗烆渻閹屾缂傚倸鍊搁崐椋庣矆娓氣偓钘濋梺顒€绉撮弸浣糕攽閻樿櫕鐨戠€规挷绶氶弻娑㈠焺閸愵亖濮囬梺绋匡功閸忔﹢寮诲☉妯锋斀闁糕剝顨忔导鈧俊鐐€栧褰掑礉閺囥垹鐓橀柟杈鹃檮閸婂鏌涢妷銏℃珖閺嶏繝姊绘担鍛婂暈闁圭ǹ顭烽幃鐑芥晜閻e备鏀虫繝鐢靛Т濞诧箓宕甸崘顔界厓闁告繂瀚弳鐔兼煥濞戞瑧鐭掓慨濠囩細閵囨劙骞掗幋婊冩瀳闂備礁鎲¢悷銉︻殽閹间礁鐓濋柟鐐灱閸亪鏌涢銈呮灁闁告ɑ鎮傞弻锝堢疀閺囩偘鎴风紒缁㈠幖閻栫厧鐣烽幋锕€绠婚悹鍥皺閻も偓濠电偠鎻徊浠嬪箟閿熺姴纾规い鏍仦閳锋垹鐥鐐村櫣濞存粌缍婇幃璺衡槈閺嵮冨Е闂佺硶鏂侀崑鎾愁渻閵堝棗绗掗柛鐕佸亰閹啫煤椤忓懐鍘告繛杈剧到濠€杈ㄦ櫠椤忓牊鐓冮悷娆忓閻忔挳鏌熼鐣屾噰鐎殿喖鐖奸獮瀣偐鏉堫煈鏁囬梻鍌氬€风粈浣革耿鏉堛劎浠氶梻浣侯攰婵倗鍒掓惔銊ョ闁圭儤顨呯猾宥夋煕椤愩倕鏋庡ù鐘烘缁辨挻鎷呴崜鎻掑壍濡炪倖娲樻繛濠囧极閸愵喖纾兼繛鎴炶壘楠炲牓姊绘担鍛婃儓婵炲眰鍨藉畷婵嗙暆閸曨剙鈧爼鏌eΟ鑲╁笡闁绘挻娲熼弻鐔兼嚋椤掆偓婵$厧霉濠婂嫬鍔ら柍瑙勫灴閺佸秹宕熼鈩冩線闂備胶枪閿曘儵鎮ч悩鑼殾婵犻潧顑嗛弲婵嬫煃瑜滈崜鐔煎灳閿曞倸閿ゆ俊銈傚亾闁绘帒鐏氶妵鍕箳瀹ュ牆鍘$紓浣哄Т婢т粙鍩€椤掆偓閸樻粓宕戦幘鏂ユ斀闁绘ǹ浜粣鏃堟煕鐎n偒娈旈柍瑙勫灴椤㈡瑧娑甸悜鐣屽弽婵犵數鍋涢幏鎴犲緤閸啣锝夊箛閺夎法顔婇梺鐟板暱绾绢參宕伴幘璇茬闁绘ḿ绮崵鎴︽煠缁嬭法浠涙慨锝嗗姍濮婂宕掑顑藉亾閻戣姤鍤勯柤鍝ユ暩娴犳碍绻濋悽闈涗粶妞ゆ洦鍙冨畷妤€螣娓氼垰娈ㄥ銈嗗姂閸婃牜鈧碍姘ㄩ埀顒傛嚀婢瑰﹪宕伴弽褉鏋旈柕濠忓缁♀偓闂佹眹鍨藉ḿ褎鐗庣紓浣哄亾濠㈡ḿ绮旈悷閭﹀殨闁哄被鍎辩粻鐢告煙閻戞ḿ绠橀柛鐐垫暬閺岋綁鎮╅悜姗嗕哗闁诲繐绻堥崝宀勵敊韫囨稑唯鐟滃宕戦幘鑸靛枂闁告洦鍓欑喊宥呪攽閳藉棗浜濈紒璇插€块敐鐐剁疀濞戞瑦鍎梺闈╁瘜閸橀箖鏁嶅⿰鍐f斀闁宠棄妫楅悘鐘绘煙绾板崬浜伴柨婵堝仜椤撳ジ宕堕埡鍐跨闯濠电偠鎻紞渚€藟閹捐绀夌€广儱顦伴悡娆戠磼鐎n亞浠㈤柡鍡涗憾閺岋綁鏁愰崶褍骞嬪Δ鐘靛仜椤戝寮崘顔肩劦妞ゆ帒鍊绘稉宥呪攽閻樺磭顣查柛瀣剁秮閺屾盯濡烽幋婵嗘殶濡ょ姴娲幃妤冩喆閸曨剙纰嶇紓浣割槹閹告娊鍨鹃弮鍫濈妞ゆ柨妲堣閺屾盯鍩勯崗鐙€浜Λ鍕吋閸モ晝锛濇繛杈剧到婢瑰﹪宕曢幇鐗堢厱闁靛ǹ鍎遍。宕囩磼椤旂⒈鍎忔い鎾冲悑瀵板嫮鈧綆浜栭崑鎾绘煥鐎c劋绨婚梺鐟版惈缁夊爼藝閿旈敮鍋撳▓鍨灈闁诲繑绻堥崺鐐哄箣閿曗偓閻擄繝鏌涢埄鍐炬畼濞寸媭鍨跺娲川婵犲海鍔堕梺鍛婃处閸欏骸煤閸涘﹣绻嗛柕鍫濈箳閸掍即鏌涢悤浣哥仸鐎规洘鍔欏畷褰掝敃閿濆懎浼庢繝纰樻閸ㄦ娊宕㈣缁傚秵銈i崘鈺佲偓鍨叏濡厧浜鹃悗姘炬嫹

简介
在介绍 OpenID 身份验证之前,我们先简要回顾一下 Project Zero 是什么。下面引用 Project Zero 站点上的话:
Project Zero 是在 IBM 公司中启动的一个孵化项目,这个项目致力于为下一代动态 Web 应用程序提供敏捷的开发方法。Project Zero 引入了一种简单的环境,可以基于流行的 Web 技术创建、组装和执行应用程序。Project Zero 环境包括一个面向 Groovy 和 PHP 的脚本运行时,且具有应用程序编程接口,这些接口针对 REST 式服务、集成 mashup 和富 Web 界面的生成进行了优化。
本文的内容
本文是包含三个部分的系列文章的最后一部分。本文讨论 Project Zero Security 以及如何使用 OpenID 身份验证、为应用程序定义安全性规则和扩展用户注册表。本文假设您已经下载了 Project Zero 并已经完成了 介绍性教程 的学习,或者自己编写过简单的应用程序。
Project Zero 主要针对的是下一代动态 Web 应用程序(通常通称为 Web 2.0),所以它主要关注交互式 Web 应用程序,这些应用程序可能会包含用户提供的内容,比如 mashup、wiki 和 blog。在 Web 2.0 时代,保持 Web 站点的安全性越来越重要了,安全性的重点在于用户提供的内容。对站点的用户进行身份验证是一项非常重要的安全需求。过去,Web 站点常常在内部维护自己的身份验证系统,包括提供一个用户注册表来存储最终用户的数字身份。
现在讨论 OpenID。OpenID 技术提供一个分散的身份验证模型,支持因特网单点登录(single sign-on,SSO)。它为最终用户提供一个可以跨 Web 使用的数字身份。通过使用 OpenID,最终用户可以拥有一个身份,从而避免将希望保护的信息暴露在外部,比如电子邮件地址。图 1 显示 OpenID 身份验证体系结构中的关键实体。
什么是 OpenID?
OpenID Foundation 把 OpenID 描述为一种用于以用户为中心的数字身份的分散的开放式免费框架。OpenID 利用现有的因特网技术(URI、HTTP、SSL、Diffie-Hellman),并认识到人们已经在 blog、图像流、个人信息页面中为自己创建了身份。通过使用 OpenID,很容易把现有的 URI 转换为一个帐户,在支持 OpenID 登录的所有站点上都可以使用这个帐户。
图 1. OpenID 体系结构
OpenID 提供者(有时候也称为身份提供者 )提供注册用户身份的服务和 OpenID 身份验证。回复方(replying party)是需要对用户进行身份验证的 Web 站点。现在在访问站点时,用户不需要使用用户名和密码,而是使用单一的 OpenID 标识符,这个标识符通常是一个 URL(Uniform Resource Locator)或 XRI(eXtensible Resource Identifier)。
为了支持这种分散的身份验证模型,Project Zero 提供一个 OpenID 消费者库,让应用程序能够对第三方 OpenID 身份提供者进行身份验证。这样,应用程序开发人员就能够把管理用户信息的任务交给可信的第三方资源,这减轻了他们的工作负担,让他们可以集中精力开发应用程序。
关于示例
为了了解如何在 Project Zero 中使用 OpenID 技术,并帮助您获得实践经验,可以下载并运行示例。这些示例涉及一系列复杂性依次增加的用例,包括以下常见的 OpenID 使用场景:
示例 1 是一个基本应用程序,它把身份验证类型配置为 OpenID。
示例 2 是在示例 1 上构建的,并提供了一个定制的用户注册表来处理各种 openid_urls 格式。
示例 3 是在示例 2 上构建的,并允许提供受支持的 OpenID 提供者的 “白名单”。
需要一个 OpenID 帐户
首先,需要注册一个 OpenID 帐户。在本文中,我们使用最常用的 OpenID 提供者之一(myopenid.com),并用一个测试 OpenID 提供者对 OpenID 进行概念证明(注意,本文中的应用程序应该可以使用支持 OpenID 规范的任何 OpenID 提供者)。
示例应用程序 1:启用 OpenID 身份验证
为了更好地了解 Project Zero OpenID 技术,可以从 Project Zero Catalog 下载本文使用的示例应用程序 openid.demo,并在学习以下内容时参考应用程序。需要正确地配置 Eclipse IDE 和 Project Zero 插件。准备好开发环境之后,把示例应用程序(openid.demo-1.0.0.zip)作为 Existing Project 导入工作空间。选择 archive file 作为源(见图 2)。Project Zero 通过 zero.security.openid 库提供对 OpenID 的支持,这个库已经在 ivy.xml 文件中配置为应用程序的依赖项之一。在第一次使用 OpenID 时,系统可能要求您把 zero.security.openid 库下载到存储库中。
图 2. 导入示例应用程序
单击 OK 解析依赖项。
这个示例应用程序只有两个 Web 页面,这是一个极其简单的 Project Zero 示例。第一个页面是索引页面(见图 3),用户可以在这个页面上的文本区域中发表评论。在发表评论时,这个应用程序使用 Ajax 技术向服务器发送一个 REST 式的请求来提交消息。然后,应用程序执行另一个 Ajax 调用,获取来自服务器的消息。尽管这不是一个非常有用的应用程序,但是它足以演示 OpenID 在 Project Zero 中的工作方式。运行示例应用程序的方法是右键单击 OpenIDExampleApplication 并选择 Run as – Project Zero Application。服务器组件已经启动了。现在,在浏览器中访问 http://localhost:8080 来测试示例应用程序(见图 3)。
图 3. OpenID 示例应用程序的索引页面(index.gt)
图片看不清楚?请点击这里查看原图(大图)。
这个示例应用程序使用一个 groovy 组件(comment.groovy;见清单 1)来处理评论的发布和获取。
清单 1. comment.groovy,用来发布和获取评论的 REST 式服务
def onCreate(){
def commentJSON = zero.json.Json.decode(request.input[])
def comment = commentJSON["comment"]
if(comment != null || comment == ""){ // user submitted a comment with content
def commentId = "Comment_" + System.currentTimeMillis()
request.headers.out.Location =
zero.core.utils.URIUtils.getRequestedUri(false) + "/" + commentId
user.commentId = comment;
request.status = java.net.HttpURLConnection.HTTP_NO_CONTENT
}
}
def onRetrieve(){
def commentId = request.params.commentId.get()
def comment = user.commentId.toString();
def result = [commentId : comment]
request.view='JSON'
request.json.output = result
zero.core.views.ViewEngine.render()
}
配置示例应用程序的安全性
示例应用程序已经准备好了,现在需要保护这些资源,防止未经身份验证的用户访问这个站点。因为我们不希望创建和维护另一个 Web 页面和用户注册表来让用户创建和存储帐户(用户名和密码),所以决定把身份验证任务委托给第三方,同时站点可以保持资源。我们利用 Project Zero 的 OpenID 支持实现这个目标并正确地配置安全规则。
为了启用 OpenID 身份验证,需要在应用程序的 zero.config 文件指定两个配置部分(见表 1)。第一个配置部分是应用程序的全局配置。表 1 说明两个配置键(openidLoginPage 和 allowedOpenidDomains),它们都是可选的。
表 1. OpenID 应用程序配置
键 | 描述 | 默认值 | 必需? |
openidLoginPage | OpenID 登录表单的 URI | openidLogin.html | 可选 |
allowedOpenidDomains | 可信 OpenID 提供者的域名列表 | 空 | 可选 |
为了在示例应用程序中启用 OpenID 身份验证,第一步是设置应用程序的 zero.config 全局配置。在这个部分中,要定义 OpenID 登录页面,让用户输入用于身份验证的 openid_url(标识符)。
清单 2. 配置 OpenID 示例 —— 应用程序配置
# specify the OpenID loginPage
@include "openid/rule.config"{
"openidLoginPage": "/openidlogin.gt"
}
第二步是配置资源以应用安全约束。这要定义下面三个配置设置:
第一部分:定义一个角色
在第一部分中定义一个角色;这是本文中第一次提到角色,角色是 Project Zero Security 的一个高级主题。这里定义的角色名为 OPENID_ROLE,属于这个组的所有用户都被称为 VALID_OPENID_USER。
第二部分:为 OpenID 定义一个安全约束
在第二部分中,为 index.gt 定义一个安全约束(index.gt 是这个应用程序的入口点)。这个约束规定,用户必须属于第一部分中定义的角色,才能使用这个资源。这个资源的 authType 定义为 RP(RP 代表 Relying Party,当前支持的惟一 RP 类型是 OpenID)。如果资源的 authType 为 RP,而且用户还没有登录,那么用户就被重定向到适当的登录页面进行身份验证。
第三部分:为 REST 式服务定义一个安全约束
在第三部分中,为 comment.groovy 定义一个安全约束,comment.groovy 是一个处理 AJAX 请求的 REST 式资源。这个约束规定,用户必须属于第一部分中定义的角色,才能使用这个资源。这个资源的 authType 是 SSO(单点登录)。使用 SSO 保护这个资源是为了方便。如果使用 RP 类型保护这个资源,那么当安全令牌过期时,AJAX 请求就被重定向到登录页面。对于非 AJAX 请求,这种情况是可以接受的;但是对于 AJAX 请求,这无法提供良好的用户体验。如果用户在尝试访问这个资源时还没有经过身份验证,那么用户会收到 401 状态码,应用程序可以提供一个特殊的错误处理函数来处理这种情况。
清单 3. 配置 OpenID 示例 —— 资源安全性
## define a role named OPENID_ROLE that only the group VALID_OPENID_USER is a member
/config/security/roles/OPENID_ROLE/groups=["VALID_OPENID_USER"]
#specify the security constraints
#protect index page
@include "security/rule.config"{
"conditions" : "/request/path =~ (/|/index.gt(/.*)?)",
"authType" : "RP",
"csrfProtect" : false,
"roles" : ["OPENID_ROLE"]
}
#protect RESTful resource with SSO so no redirects
#to login page for the case of expired tokens.
@include "security/rule.config"{
"conditions" : "/request/path =~ /resources/comment(/.*)?",
"authType" : "SSO",
"csrfProtect" : true,
"roles" : ["OPENID_ROLE"]
}
访问受保护的资源
在创建用户 ID(参见 “需要一个 OpenID 帐户” 一节)之后,就可以访问应用程序了。第一步是打开浏览器,访问 http://localhost:8080/index.gt,这是应用程序的主入口点。因为这个资源的 authType 是 RP,Zero Security 运行时会注意到这个资源是受保护的,并把用户重定向到上面定义的 openidLoginPage。现在应该会在浏览器中看到图 4 所示的页面。
图 4. OpenID 示例应用程序的登录表单(openidlogin.gt)
图片看不清楚?请点击这里查看原图(大图)。
登录表单包含清单 4 所示的代码,文件名是 openidlogin.gt。
清单 4. openidlogin.gt 登录表单的 HTML 代码
<form name="input" action="" method="POST">
<table>
<tr>
<td class="header">OpenID URL: </td>
<td><input type="text" name="openid_url" value=""></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" name="submit" value="Login"></td>
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error: The previous line is longer than the max of 90 characters ---------|
</tr>
</table>
</form>
现在,我们使用 myopenid.com 提供的 openid_url(todkap.myopenid.com)登录。由于使用了 OpenID,登录请求被重定向到 myopenid.com 并在这个站点上用 opened_url 和密码进行身份验证(见图 5)。
图 5. myopenid.com 的登录表单
图片看不清楚?请点击这里查看原图(大图)。
成功地向 OpenID 提供者(myopenid.com)证明身份之后,OpenID 提供者将把用户重定向回原来请求的页面(http://localhost:8080/index.gt),这个页面现在显示 RemoteUser、用户所属的组和角色。RemoteUser 是用来登录的 openid_url。组列表只包含一个组 VALID_OPENID_USER,角色只有 OPENID_ROLE。如果情况不是这样,用户就没有通过身份验证,因为只允许 OPENID_ROLE 角色中的用户访问这个资源。图 6 显示成功的身份验证之后浏览器应该显示的内容。
图 6. 用户登录之后的索引页面
图片看不清楚?请点击这里查看原图(大图)。
现在,可以安全地发布评论了。
示例应用程序 2:用 Project Zero 扩展 OpenID 支持
既然基本的 OpenID 支持已经起作用了,我们就来扩展默认的事件处理函数和默认的用户注册表实现,让 OpenID 帐户能够转换为受支持的 Project Zero 本地帐户。在把因特网 SSO 与公司内部网安全系统连接起来时,这个功能非常有用。
定义定制的 resolveFederatedId 事件处理函数
resolveFederatedId 是一个事件处理函数,这个事件在请求处理期间的安全和授权事件之间引发。当用户用联邦 ID(比如 OpenID)登录时,会增加这个事件。有时候,为了让第三方身份验证者和 Project Zero 的用户注册表都能够使用用户 ID,需要对用户 ID 做一些修改(或转换)。如果 openid_url 由内部 OpenID 提供者(例如,供 IBM 内部 OpenID 身份验证使用的 'blueid.bluehost.ibm.com')拥有,那么可以只使用电子邮件地址。IBM 在各种 SSO 解决方案中常常使用电子邮件地址,包括处理 IBM 目录。清单 5 给出一个扩展 OpenIDResolver 的默认实现的事件处理函数。它覆盖了 attachUserToken 方法调用;默认实现调用这个方法来创建一个令牌,这个令牌用于在登录之后识别用户。覆盖的 attachUserToken 以经过身份验证的用户名为参数,检查它是否以变量 TRUSTED_OPENID_SERVER 开头。如果匹配,就从用户名中删除这一部分。
清单 5. 定制的 resolveFederatedId 事件处理函数代码
package zero.security.example.openid;
import zero.core.security.relying.party.openid.OpenidResolver;
public class ExampleOpenidResolver extends OpenidResolver{
private static final String TRUSTED_OPENID_SERVER =
"http://blueid.bluehost.ibm.com/?user=";
@Override
public void onResolveFederatedId() {
super.onResolveFederatedId();
}
@Override
protected void attachUserToken(String username) {
if (username.startsWith(TRUSTED_OPENID_SERVER)){
// consider this user trusted for this app and
//just use the userid in token and remoteUser
username = username.substring(TRUSTED_OPENID_SERVER.length());
}
super.attachUserToken(username);
}
}
清单 6 所示的配置演示如何配置定制的 resolveFederatedId 处理函数。在下载的示例中,这些代码被注释掉了。如果要在您的环境中进行测试,请务必删除这些配置项的注释标志。
清单 6. 定制的 resolveFederatedId 配置
/config/handlers += [{
"events" : "resolveFederatedId",
"handler" : "zero.security.example.openid.ExampleOpenidResolver.class"
}]
定义定制的 UserService 实现
除了添加定制的 resolveFederatedId 之外,我们还想演示如何创建定制的 UserService。在清单 7 所示的示例中,扩展了 OpenID 身份验证所用的默认 UserService 实现。在定制的实现类中,调用默认实现的 getUser 和 login 来获得适当的用户集。然后,添加一个定制组 DWExampleGroup,演示如何为特定用户添加额外的组。定制的 resolveFederatedId 只对内部 IBM OpenID 提供者进行检查,而定制的 UserService 对于任何 OpenID 提供者都会添加这个定制组。
清单 7. 定制的 UserRegistry 实现代码
package zero.security.example.openid;
import java.security.Principal;
import java.security.acl.Group;
import java.util.Set;
import zero.core.security.GroupImpl;
import zero.core.security.relying.party.openid.OpenIDUserService;
import zero.core.security.userservice.UserServiceException;
public class ExampleUserService extends OpenIDUserService{
private static final Group DW_GROUP = new GroupImpl("DWExampleGroup");
@Override
public Set<Principal> getUser(String username)
throws UserServiceException {
Set<Principal> principals = super.getUser(username);
if(principals.isEmpty() == false) { // user was logged in via openID
principals.add(DW_GROUP); // add developer work group
}
return principals;
}
@Override
public Set<Principal> login(String username, String passwd)
throws UserServiceException {
Set>Principal< principals = super.login(username, passwd);
if(principals.isEmpty() == false) { // user was logged in via openID
principals.add(DW_GROUP); // add developer work group
}
return principals;
}
}
清单 8 中的配置演示如何配置定制的 UserService.
清单 8. 定制 UserService 的配置
registryImplStr="zero.security.example.openid.ExampleUserService"
/config/security/userservice/registryType="exampleUserService"
# must implement zero.core.security.userservice.UserService
/config/security/userservice/registryImpl/exampleUserService=${registryImplStr}
演示示例 2
我们已经给应用程序配置了定制的 resolveFederatedId 和 UserService 实现,现在需要重新启动应用程序,让配置生效。现在再次访问受保护的应用程序。在前一个示例中,我们使用的 openid_url 是 todkap.myopenid.com。这一次使用的 openid_url 是 http://blueid.bluehost.ibm.com/?user=todkap@us.ibm.com,这是为了演示新配置的特性。
首先进入与前面一样的登录表单。但是,这一次用 IBM OpenID 服务提供的 openid_url(http://blueid.bluehost.ibm.com/?user=todkap@us.ibm.com)登录。这会把用户重定向到 OpenID 提供者登录页面(见图 7):
图 7. IBM OpenID 提供者的登录表单
图片看不清楚?请点击这里查看原图(大图)。
身份验证请求现在被转发到 IBM 内部网 OpenID 站点 blueid.bluehost.ibm.com,而不是 myopenid.com。向 OpenID 提供者成功地验证身份之后,OpenID 提供者将把用户重定向回原来请求的页面(http://localhost:8080/index.gt),这个页面现在显示 RemoteUser、用户所属的组和角色。这里的差异在于,远程用户是用来登录的 openid_url 经过修改后的版本(注意:resolveFederatedId 修改了这个用户 ID,只留下用户的电子邮件地址)。组列表现在包含两个组:原来的 'VALID_OPENID_USER' 和通过 UserService 新添加的 'DWExampleGroup'。角色是 OPENID_ROLE。如果情况不是这样,用户就没有通过身份验证,因为只允许 'OPENID_ROLE' 角色中的用户访问这个资源。图 8 显示成功的身份验证之后浏览器应该显示的内容。
图 8. 用户登录之后的索引页面
图片看不清楚?请点击这里查看原图(大图)。
现在,可以发布评论了。
示例应用程序 3:只使用可信的 OpenID 提供者
我们已经看到了如何在两个常见场景中使用 OpenID。OpenID 的缺点之一是,提供 OpenID 提供者服务的任何站点都可以声明用户的身份是有效的。回复方(您的 Web 站点)很难信任所有这些声明。为了解决这个问题,Zero 提供了一个配置选项,用来限制应用程序可信任的 OpenID 提供者站点。清单 9 中的示例演示如何启用这个配置,以及如果指定的 openid_url 来自不可信域,会发生什么情况。注意,尽管这个功能可以通过 JavaScript 代码在客户端上实现,但是检验总是应该在服务器上进行,以防止攻击者篡改客户机代码。
清单 9. 配置可信 OpenID 提供者的白名单
@include "openid/rule.config"{
"openidLoginPage" : "/openidlogin.gt",
"allowedOpenidDomains" = ["myopenid.com",
"verisignlabs.com", "blueid.bluehost.ibm.com"]
}
我们已经配置了这个选项,现在重新启动应用程序并尝试使用一个不可信的 OpenID 提供者。在这个示例中,使用一个虚构的 openid_url 'http://myuntrusteduser.someunknownsite.com'。这会导致客户机上产生一个错误消息,它指出 openid_url 的提供者没有列在 allowedOpenidDomains 列表中(见图 9)。
图 9. 不可信 OpenID 提供者错误页面
图片看不清楚?请点击这里查看原图(大图)。
结束语
OpenID 使应用程序能够依靠第三方身份验证提供者来处理身份验证,从而提高了应用程序部署的灵活性。因为越来越多的用户希望只用一个用户身份访问多个站点(包括 blog、wiki 和其他社会网络活动),所以 OpenID 这样的提供者会越来越普及。另外,许多 Web 站点不愿意自行维护用户个人信息,也不愿意要求用户提供这些信息。我们希望本文能够帮助您掌握如何在 Project Zero 平台上使用 OpenID 技术实现这种分散的身份验证,希望整个系列能够帮助您在 Zero 应用程序中实现所有重要的安全特性。作为由用户驱动、快速发展的 Web 2.0 应用程序的开发人员,您必须意识到安全性对于您的用户和业务是多么重要。
- ››保持Photoshop与显示器色彩模式统一
- ››保持 Project Zero 和 WebSphere sMash 应用程序的...
- ››保持 Project Zero 和 WebSphere sMash 应用程序的...
- ››保持 Project Zero 和 WebSphere sMash 应用程序的...
- ››保持并关闭Excel数据链接更新提示
- ››保持进程在Shell退出后能继续运行方法
- ››保持C/C++程序代码的可伸缩性
- ››保持你对Java的敏感度
- ››保持 EJB 技术的所有优点而不增加 RMI 开销
- ››保持对Java的敏感度切莫忽视思想研究
- ››Project JXTA 中对等管道的构建
- ››保持MySQL安全
更多精彩
赞助商链接