Connecting to OpenID services
OpenID 是一种使用一个账号访问多个服务的协议。作为一个 web 开发者,你可以使用 OpenID 让用户用他们已有的账号(例如 Google 账号)来进行登录。在企业中,你可以使用 OpenID 来连接公司的 SSO 服务器。
OpenID 工作流程一览
- 用户给你他的 OpenID(一个 URL)。
- 你的服务器检查 URL 后面的内容,然后产生一个 URL,并将用户重定向到那。
- 用户在他的 OpenID 提供方那确认授权,然后重定向回你的服务器。
- 你的服务器收到重定向返回的信息,并与 OpenID 提供方检查信息是否正确。
如果你的用户使用的都是同一个 OpenID 提供方,那么可以忽略第一步(例如你决定全部都使用 Google 账号来登录)。
用法
使用 OpenID,首先需要把 ws 库添加到你的 build.sbt 文件中:
libraryDependencies ++= Seq(ws)
在 Play 中使用 OpenID
OpenID API 有两个重要的函数:
OpenID.redirectURL计算用户需要重定向的 URL,这个过程包括异步地获取用户的 OpenID 页面,这就是为什么它返回的是Future[String]。如果 OpenID 是无效的,返回的Future就会失败。OpenID.verifiedId需要一个隐式的Request,并且检查它来建立用户的信息,包含他验证过的 OpenID。它会异步地请求一下 OpenID 服务器以确认信息的真实性,这也是为什么它返回的是一个Future[UserInfo]。如果信息不正确或者服务器的检查结果不正确(例如重定向 URL 是伪造的),返回的Future就会失败。
如果 Future 失败,你可以定义一个回退将用户重定向回登录页面或者返回 BadRequest。
下面请看一个用例:
def login = Action {Ok(views.html.login())}def loginPost = Action.async { implicit request =>Form(single("openid" -> nonEmptyText)).bindFromRequest.fold({ error =>Logger.info("bad request " + error.toString)Future.successful(BadRequest(error.toString))},{ openId =>OpenID.redirectURL(openId, routes.Application.openIDCallback.absoluteURL()).map(url => Redirect(url)).recover { case t: Throwable => Redirect(routes.Application.login) }})}def openIDCallback = Action.async { implicit request =>OpenID.verifiedId.map(info => Ok(info.id + "\n" + info.attributes)).recover {case t: Throwable =>// Here you should look at the error, and give feedback to the userRedirect(routes.Application.login)}}
扩展属性
用户的 OpenID 给你的是他的身份标识,该协议也支持获取一些扩展属性,如 Email 地址,名或者姓。
你可以从 OpenID 服务器请求一些可选属性或必需属性。要求提供某些必需属性意味着如果用户没有提供的话,他将无法登录你的服务。
你在重定向 URL 中请求扩展属性:
OpenID.redirectURL(openid,routes.Application.openIDCallback.absoluteURL(),Seq("email" -> "http://schema.openid.net/contact/email"))
这样一来,OpenID 服务器提供的 UserInfo 中就会有这个属性了。
