T2サンプルでOpenIDを使ったサンプルを追加しました
OpenIDの仕組みに興味が会ったので、T2でOpenIDを使った認証のサンプルを作りました。
OpenIDのリクエスト部分としては、openid4javaを使いました。
今のところ一番簡易な認証だけなので、本当はもう少しやり取りが必要かもしれませんが
少なくともWebフレームワークなんだし、OpenIDとのインテグレーション入れてみようと思った次第です。
サンプルを一番下にはります。
authenticateRequestメソッドがユーザから呼び出されるメソッドです。
わたってくるパラメータはOpenIDの認証先です。例えば、myname.openid.ne.jpみたいな感じ。
authenticateRequestメソッドの中ではOpenIdの認証局に行ったあとのコールバックする先を指定します。
ttp://localhost:8080/t2-samples/openid/acceptのようなURLにコールバックして欲しいので
下記のようにします。
それがauthenticateRequestメソッドの下記の部分です。
String returnToUrl = request.getRequestURL().append("/accept")
.toString();
ttp://localhost:8080/t2-samples/openid/acceptに対応するPageクラスのアクションメソッドを作ります。
メソッドはURLにそのままひもづかせたいので、acceptメソッドとして、以下のような感じになります。
OpenIDからのコールバックの結果をverifyResponseメソッドで検査してます。
@GET @ActionPath public Navigation accept(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { Identifier identifier = null; try { identifier = this.verifyResponse(req); } catch (OpenIDException ex) { logger.debug(ex.getMessage()); } logger.debug("identifier: " + identifier); if (identifier == null) { return Forward.to("/jsp/openid.jsp"); } else { req.setAttribute("identifier", identifier.getIdentifier()); return Forward.to("/jsp/openidResult.jsp"); } }
重要なのは、verifyResponseメソッドで呼び出しているConsumerManager#verify(String receivingUrl, ParameterList response, DiscoveryInformation discovered)です。
こいつで実際にOpenIDで接続許可がとれたかどうか、その認証は期限内かどうかなどを見ています。
もっと突き詰めていけば色々出来そうですが、T2のリリースも迫っているのでこの辺にしておきます。
また今度見直してみます。
ソース全文は下記からどうぞ。
package examples.page; import java.io.IOException; import java.util.Iterator; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.openid4java.OpenIDException; import org.openid4java.consumer.ConsumerException; import org.openid4java.consumer.ConsumerManager; import org.openid4java.consumer.VerificationResult; import org.openid4java.discovery.DiscoveryInformation; import org.openid4java.discovery.Identifier; import org.openid4java.message.AuthRequest; import org.openid4java.message.AuthSuccess; import org.openid4java.message.ParameterList; import org.openid4java.message.ax.AxMessage; import org.openid4java.message.ax.FetchRequest; import org.openid4java.message.ax.FetchResponse; import org.t2framework.commons.annotation.composite.RequestScope; import org.t2framework.commons.util.Logger; import org.t2framework.t2.annotation.composite.GET; import org.t2framework.t2.annotation.composite.POST; import org.t2framework.t2.annotation.core.ActionParam; import org.t2framework.t2.annotation.core.ActionPath; import org.t2framework.t2.annotation.core.Default; import org.t2framework.t2.annotation.core.Page; import org.t2framework.t2.annotation.core.RequestParam; import org.t2framework.t2.contexts.WebContext; import org.t2framework.t2.navigation.Forward; import org.t2framework.t2.navigation.NoOperation; import org.t2framework.t2.navigation.Redirect; import org.t2framework.t2.spi.Navigation; /** * OpenID verification with T2 using openid4java. * * @author shot * */ @RequestScope @Page("/openid") public class OpenIdPage { protected static Logger logger = Logger.getLogger(OpenIdPage.class); @Default public Navigation index(WebContext context) throws ConsumerException { try { ConsumerManager manager = new ConsumerManager(); context.getSession().setAttribute("manager", manager); return Forward.to("/jsp/openid.jsp"); } catch (ConsumerException ex) { throw ex; } } @POST @ActionParam("login") @SuppressWarnings("unchecked") public Navigation authenticateRequest(WebContext context, HttpServletRequest request, HttpServletResponse response, @RequestParam("identifier") String identifier) throws OpenIDException, IOException { logger.debug("identifier:" + identifier); ConsumerManager manager = context.getSession().getAttribute("manager"); String returnToUrl = request.getRequestURL().append("/accept") .toString(); List discoveries = manager.discover(identifier); DiscoveryInformation discovered = manager.associate(discoveries); request.getSession().setAttribute("openid-disc", discovered); AuthRequest authReq = manager.authenticate(discovered, returnToUrl); FetchRequest fetch = setupFetchRequest(request); authReq.addExtension(fetch); if (discovered.isVersion2() == false) { final String path = authReq.getDestinationUrl(true); return Redirect.toOuterUrl(path); } else { return NoOperation.noOp(); } } protected FetchRequest setupFetchRequest(final HttpServletRequest request) { FetchRequest fetch = FetchRequest.createFetchRequest(); if ("1".equals(request.getParameter("nickname"))) { fetch.addAttribute("nickname", "http://schema.openid.net/contact/nickname", true); } return fetch; } @GET @ActionPath public Navigation accept(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { logger.debug("------------------------"); Identifier identifier = null; try { identifier = this.verifyResponse(req); } catch (OpenIDException ex) { logger.debug(ex.getMessage()); } logger.debug("identifier: " + identifier); if (identifier == null) { return Forward.to("/jsp/openid.jsp"); } else { req.setAttribute("identifier", identifier.getIdentifier()); return Forward.to("/jsp/openidResult.jsp"); } } @SuppressWarnings("unchecked") protected Identifier verifyResponse(HttpServletRequest request) throws OpenIDException { ConsumerManager manager = (ConsumerManager) request.getSession() .getAttribute("manager"); ParameterList response = new ParameterList(request.getParameterMap()); DiscoveryInformation discovered = (DiscoveryInformation) request .getSession().getAttribute("openid-disc"); StringBuffer buf = request.getRequestURL(); String queryString = request.getQueryString(); if (queryString != null && queryString.length() > 0) { buf.append("?").append(request.getQueryString()); } String receivingUrl = new String(buf); VerificationResult verification = manager.verify(receivingUrl, response, discovered); Identifier verified = verification.getVerifiedId(); if (verified == null) { logger.debug("verified is null(url:{}, verification:{}).", new Object[] { receivingUrl, verification }); return null; } else { AuthSuccess authSuccess = (AuthSuccess) verification .getAuthResponse(); if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) { FetchResponse fetchResp = (FetchResponse) authSuccess .getExtension(AxMessage.OPENID_NS_AX); List<String> emails = fetchResp.getAttributeValues("email"); String email = emails.get(0); logger.debug("email:" + email); List<String> aliases = fetchResp.getAttributeAliases(); for (Iterator<String> iter = aliases.iterator(); iter.hasNext();) { String alias = iter.next(); List values = fetchResp.getAttributeValues(alias); if (values.size() > 0) { logger.debug(alias + " : " + values.get(0)); request.setAttribute(alias, values.get(0)); } } } return verified; } } }