ikeike443のブログ

ソフトウェアビジネスに関心がある系のブログ

PlayframeworkでCookieにSecureフラグを立てられるように応急処置

http://d.hatena.ne.jp/ikeike443/20100505/1273040748
もう一ヶ月も経っちゃったけど、上記で報告したバグについて、とりあえず応急処置的な修正をしてみた。

    /**
     * An HTTP Cookie
     */
    public static class Cookie implements Serializable {
    	//add by ikeda 2010.06.01
    	static boolean secureflag;
    	static{
     Properties p = Play.configuration;
     secureflag = Boolean.parseBoolean(p.getProperty("ikeda.http.cookie.secure", "false"));
    	}


        /**
         * Cookie name
         */
        public String name;
        /**
         * Cookie domain
         */
        public String domain;
        /**
         * Cookie path
         */
        public String path = "/";
        /**
         * for HTTPS ?
         */
        public boolean secure = secureflag;/*false;*/ //mod by ikeda 2010.06.01 
        /**
         * Cookie value
         */
        public String value;
        /**
         * Cookie max-age
         */
        public Integer maxAge;
        /**
         * Don't use
         */
        public boolean sendOnError = false;
    }

application.confの"ikeda.http.cookie.secure"という設定を見て動くようにした。
でも、On/Offしか出来ないのでこれじゃ不十分だなー。。後で改めて直すか。。

id:nkmrshn さんにプロトコル見て自動でsecureをセットしてくれるといいよねーという指摘をもらったのでつらつらコード見てましたが、たぶんこんなんで動くんじゃないでしょうか。(未検証。。)

//play.server.ServletWrapperの一部抜粋

    public void copyResponse(Request request, Response response, HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException {
        if (response.contentType != null) {
            servletResponse.setHeader("Content-Type", response.contentType + (response.contentType.startsWith("text/") ? "; charset=utf-8" : ""));
        } else {
            servletResponse.setHeader("Content-Type", "text/plain;charset=utf-8");
        }

        servletResponse.setStatus(response.status);
        if (!response.headers.containsKey("cache-control")) {
            servletResponse.setHeader("Cache-Control", "no-cache");
        }
        Map<String, Http.Header> headers = response.headers;
        for (Map.Entry<String, Http.Header> entry : headers.entrySet()) {
            Http.Header hd = entry.getValue();
            String key = entry.getKey();
            for (String value : hd.values) {
                servletResponse.setHeader(key, value);
            }
        }

        
        Map<String, Http.Cookie> cookies = response.cookies;
        for (Http.Cookie cookie : cookies.values()) {
            Cookie c = new Cookie(cookie.name, cookie.value);
            //c.setSecure(cookie.secure);
            c.setSecure((servletRequest.getScheme().equalsIgnoreCase("HTTPS")));//mod by ikeda 2010.06.01
            Logger.info("servletRequest.getScheme(): "+servletRequest.getScheme());//mod by ikeda 2010.06.01
            c.setPath(cookie.path);
            if (cookie.domain != null) {
                c.setDomain(cookie.domain);
            }
            if (cookie.maxAge != null) {
                c.setMaxAge(cookie.maxAge);
            }
            servletResponse.addCookie(c);
        }

要は、ServletWrapperならHttpServletRequestに触れるのでそれでなんとか出来るよねーという。。
Playのデプロイ方法には、Playそのままでデプロイする方法と、warにしてTomcatやJettyのようなコンテナにデプロイする方法と二つ有ります。
後者であれば、ServletWrapperを通るのでなんとかなるんかなー。。

素のPlayだとHttpHandlerを通ります。
こっちの方はMinaっていうのを使ってるので上手くいかなかったです。。


2010年6月4日追記:
本家Playの1.1にて、application.confに下記の設定が追加されたのを確認しました。
application.session.secure=false
これをいじればsecureフラグのOn/Offは可能のようです。
尚、プロトコルを見て自動で、っていう方向には今のところしないみたいです。