読者です 読者をやめる 読者になる 読者になる

SAStrutsでOpenID認証してみた


試したのは、SAStruts+Mayaaの組み合わせ。



openid4java -


OpenID 2.0 Java Libraries - Google Project Hosting
を参考にして作ったが、verifyが一向に通らない。


シーサー株式会社

verification = consumerManager.verify(url, openidResp, discovered);
で使用するURLなんですが、サンプルではrequest.getRequestURLから取得しているんですが、cubbyだと返ってくる値が実際のパスとは違っていてエラーになりました。仕方ないんで固定値を設定しています。


うーん、SAStrutsでも違うのかなと思って見てみると、SAStrutsでも取得しているURLは違うみたい。


ここは同じように固定値にしたが、それでも通らない。

色々調べた結果、どうやらrequest.getQueryString()が書き換わっている様子。

request.getAttribute("javax.servlet.forward.query_string");

ここから取るみたい。


以下、ソース。
ConsumerManager はcomponentにSingletonで定義してあります。
あとMayaaと最新のOpenID4Javaで使っているnekoHtmlのバージョンが違うため、0.9.3を使用しています。最新のはSVNから引っ張ってきてantでbuildすればできます。
0.9.4でRealmVerifierのエラーが出た場合は、consumerManagerをnewした後に以下を設定しておけばOK。
http://code.google.com/p/openid4java/issues/detail?id=45&can=1&q=Realm

RealmVerifier verifier = new RealmVerifier();
verifier.setEnforceRpId(false);
consumerManager.setRealmVerifier(verifier);
public class LoginAction {

	@Resource
	protected ConsumerManager consumerManager;

	@Resource
	protected HttpServletRequest request;

	@Resource
	protected HttpServletResponse response;

	/** 入力 */
	@Required(target = "openid")
	public String openidUrl;

	@Required(target = "hatena")
	public String hatenaid;

	private final static String targetURL =
		"http://localhost:8080/openid/login/verify";

	@Execute(validator = false)
	public String index() {
		return "login.html";
	}

	@Execute(validator = true, input = "login.html")
	public String openid() {
		AuthRequest authReq = auth(openidUrl);
		if (authReq != null) {
			try {
				response.sendRedirect(authReq.getDestinationUrl(true));
				return null;

			} catch (IOException e) {
				// TODO present error to the user
			}
		}
		return "/error/?redirect=true";
	}

	@Execute(validator = true, input = "login.html")
	public String hatena() {

		String discoverUrl = "http://www.hatena.ne.jp/" + hatenaid + "/";
		AuthRequest authReq = auth(discoverUrl);
		if (authReq != null) {
			try {
				response.sendRedirect(authReq.getDestinationUrl(true));
				return null;
			} catch (IOException e) {
				// TODO present error to the user
			}
		}
		return "../?redirect=true";
	}

	private AuthRequest auth(String discoverUrl) {
		try {
			List discoveries = consumerManager.discover(discoverUrl);

			DiscoveryInformation discovered =
				consumerManager.associate(discoveries);

			request.getSession().setAttribute("openid-disc", discovered);

			SRegRequest sregReq = SRegRequest.createFetchRequest();
			sregReq.addAttribute("email", true);

			AuthRequest authReq =
				consumerManager.authenticate(discovered, targetURL);
			authReq.addExtension(sregReq);

			return authReq;

		} catch (OpenIDException e) {
			// TODO present error to the user
		}
		return null;
	}

	@Execute(validator = false)
	public String verify() {
		try {
			ParameterList response =
				new ParameterList(request.getParameterMap());

			DiscoveryInformation discovered =
				(DiscoveryInformation) request.getSession().getAttribute(
					"openid-disc");

			StringBuilder receivingURL = new StringBuilder(targetURL);
			
			String queryString = (String)request.getAttribute("javax.servlet.forward.query_string");
			if (queryString != null && queryString.length() > 0)
				receivingURL.append("?").append(queryString);
			
			VerificationResult verification =
				consumerManager.verify(
					receivingURL.toString(),
					response,
					discovered);

			Identifier verified = verification.getVerifiedId();
			if (verified != null) {
				AuthSuccess authSuccess =
					(AuthSuccess) verification.getAuthResponse();

				if (authSuccess.hasExtension(SRegMessage.OPENID_NS_SREG)) {
					MessageExtension ext =
						authSuccess.getExtension(SRegMessage.OPENID_NS_SREG);

					if (ext instanceof SRegResponse) {
						SRegResponse sregResp = (SRegResponse) ext;
						String email = sregResp.getAttributeValue("email");
						System.out.println("EMAIL:" + email);
					}
				}
				System.out.println("SUCCESS");
				return "registration.html"; // success
			}
		} catch (OpenIDException e) {
			// TODO present error to the user
		}
		return "registration.html";

	}
}