サーブレットフィルタによる署名検証
OpenSocialコンテナは外部サーバにリクエストを発行する機能があります。gadgets.io.makeRequest()を使ってリソースを取得したり、データを送信したりできます。
var xapp = {}; xapp.configuration = { endpoint: 'http://example.com/api'; }; xapp.query = function (resourceName, cb) { var params = {}; params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET; params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED; params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON; return gadgets.io.makeRequest(xapp.configuration.endpoint+resourceName, cb, params); }; // 外部からJSONリソースを取得 xapp.query('/count/today');
上記では http://example.com/api/count/today をGETしています。一般的なGETリクエストなので、サーバサイドは普段使っているWebフレームワークで実装できます。JavaであればRESTフレームワークのJerseyが使いやすいと思います。
OpenSocialコンテナからのリクエストには電子署名が付加されており、リクエストの正当性を検証できるようになっています。第三者からのリクエストを許可すると、ユーザIDを偽装されるおそれがあります。リクエストを受け付けるたびに署名検証を行う必要があります。
サーブレットフィルタを使えば簡単に署名検証が可能です。各サーブレットの先頭に署名検証処理を入れる必要はありません。自動的にやってくれます。
ソースコードの抜粋を載せておきます。HTTPリクエストごとにdoFilter()が実行され、OpenSocialコンテナからの署名が検証されます。検証エラーの場合ですが、RESTでは403を返せばよいと思います。
package org.hidetake.util.oauth; public class MixiOAuthFilter implements Filter { private final MixiOAuthValidator validator = new MixiOAuthValidator(); @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { // ローカルからのアクセスは検証しない if(req.getRemoteAddr().equals("127.0.0.1")) { log.info("OAuth signature verification was skipped: 127.0.0.1"); } else { try { validator.validateMessage((HttpServletRequest) req); } catch (OAuthException e) { // 検証エラーの場合は403を返す HttpServletResponse httpRes = (HttpServletResponse) res; httpRes.sendError(HttpServletResponse.SC_FORBIDDEN); log.error("OAuth signature verification failed: " + e.getLocalizedMessage()); return; } catch (URISyntaxException e) { throw new ServletException(e); } } chain.doFilter(req, res); }
web.xmlには以下を追記します。
<filter> <filter-name>oauth-filter</filter-name> <filter-class>org.hidetake.util.oauth.MixiOAuthFilter</filter-class> </filter> <filter-mapping> <filter-name>oauth-filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>