§Play 中的 OpenID 支援
OpenID 是一種讓使用者使用單一帳戶存取多項服務的通訊協定。身為網路開發人員,您可以使用 OpenID 為使用者提供一種使用他們既有帳戶(例如他們的 Google 帳戶)登入的方式。在企業中,您或許可以使用 OpenID 連線到公司的 SSO 伺服器。
§OpenID 流程簡述
- 使用者提供他的 OpenID(一個 URL)給您。
- 您的伺服器會檢查 URL 後面的內容,以產生您需要將使用者重新導向的 URL。
- 使用者在其 OpenID 提供者上確認授權,並重新導向回您的伺服器。
- 您的伺服器從該重新導向接收資訊,並與提供者檢查資訊是否正確。
如果您的所有使用者都使用相同的 OpenID 提供者(例如,如果您決定完全依賴 Google 帳戶),則可以省略步驟 1。
§用法
若要使用 OpenID,請先將 openId
新增至您的 build.sbt
檔案
libraryDependencies ++= Seq(
openId
)
現在,任何想要使用 OpenID 的控制器或元件都必須宣告對 OpenIdClient 的依賴關係。
§OpenID 在 Play 中
OpenID API 有兩個重要的功能
OpenIdClient.redirectURL
計算您應該將使用者重新導向的 URL。它涉及非同步擷取使用者的 OpenID 頁面,這就是它傳回CompletionStage<String>
的原因。如果 OpenID 無效,傳回的CompletionStage
將以例外完成。OpenIdClient.verifiedId
檢查目前的請求以建立使用者資訊,包括其經過驗證的 OpenID。它會非同步呼叫 OpenID 伺服器以檢查資訊的真實性,傳回 UserInfo 的承諾。如果資訊不正確或伺服器檢查為 false(例如,如果重新導向 URL 已偽造),傳回的CompletionStage
將以例外完成。
如果CompletionStage
失敗,您可以定義一個備用方案,將使用者重新導向回登入頁面或傳回BadRequest
。
§範例
conf/routes
:
GET /openID/login controllers.OpenIDController.login()
POST /openID/login controllers.OpenIDController.loginPost(request: Request)
GET /openID/callback controllers.OpenIDController.openIDCallback(request: Request)
控制器
package controllers;
import java.util.*;
import java.util.concurrent.CompletionStage;
import javax.inject.Inject;
import play.data.*;
import play.libs.openid.*;
import play.mvc.*;
import play.twirl.api.Html;
public class OpenIDController extends Controller {
@Inject OpenIdClient openIdClient;
@Inject FormFactory formFactory;
public Result login() {
return ok(views.html.login.render(""));
}
public CompletionStage<Result> loginPost(Http.Request request) {
// Form data
DynamicForm requestData = formFactory.form().bindFromRequest(request);
String openID = requestData.get("openID");
CompletionStage<String> redirectUrlPromise =
openIdClient.redirectURL(
openID, routes.OpenIDController.openIDCallback().absoluteURL(request));
return redirectUrlPromise
.thenApply(Controller::redirect)
.exceptionally(throwable -> badRequest(views.html.login.render(throwable.getMessage())));
}
public CompletionStage<Result> openIDCallback(Http.Request request) {
CompletionStage<UserInfo> userInfoPromise = openIdClient.verifiedId(request);
CompletionStage<Result> resultPromise =
userInfoPromise
.thenApply(userInfo -> ok(userInfo.id() + "\n" + userInfo.attributes()))
.exceptionally(
throwable -> badRequest(views.html.login.render(throwable.getMessage())));
return resultPromise;
}
public static class views {
public static class html {
public static class login {
public static Html render(String msg) {
return javaguide.ws.html.login.render(msg);
}
}
}
}
}
§延伸屬性
使用者的 OpenID 可提供其身分。此協定也支援取得延伸屬性,例如電子郵件地址、名字或姓氏。
您可以向 OpenID 伺服器要求選用屬性及/或必要屬性。要求必要屬性表示如果使用者未提供這些屬性,則無法登入您的服務。
延伸屬性會在重新導向 URL 中要求
Map<String, String> attributes = new HashMap<>();
attributes.put("email", "http://schema.openid.net/contact/email");
CompletionStage<String> redirectUrlPromise =
openIdClient.redirectURL(
openID, routes.OpenIDController.openIDCallback().absoluteURL(request), attributes);
屬性接著會在 OpenID 伺服器提供的 UserInfo
中提供。
下一步:存取受 OAuth 保護的資源
在此文件發現錯誤?此頁面的原始程式碼可在此處找到here。在閱讀文件準則後,請隨時貢獻一個 pull 要求。有問題或建議要分享?前往我們的社群論壇與社群展開對話。