2009年8月18日火曜日

HTTP CookieとFlash Cookieとで同期を行う

このブログ記事をはてなブックマークに追加

前回に引き続き、今回もCookie関連の記事だ。ITmediaユーザーが制御できない「秘密cookie」、半数強のサイトが利用という記事で、「ユーザーが削除したHTTP cookieを、Flash cookieを使って復活させているケース」があると書かれているが、技術的には簡単だ。

まず、HTMLのhead内にJavaScriptでdocument.cookieを設定・取得する関数を定義する。Flash (ActionScript 3.0)側では、flash.external.ExternalInterfaceを利用してHTTP Cookieを取得する。もし、取得できなければFlash Cookie (Local Shared Object, LSO)の取得を試みる。両方とも取得できない場合は、初めての利用と判断される。どちらか一方を取得できたのなら、もう一方に対して取得した値を渡す。これにより、どちらかが削除されたとしても再読み込みした際に、HTTP CookieとFlash Cookieとで同期され、削除されたデータは復元する。

異なるCookieの同期はデータの永続性を強固にする利点があるが、削除したつもりのデータが実は消えていないということも起こり得るわけで、セキュリティの面からするとあまり良くないかもしれない。これを防ぐためには、Cookieの制御に関する正しい知識を持つしかないだろう。前回の記事でも書いたが、Flash Cookieについてはグローバルストレージ設定パネルの「今後表示しない」を選択することで禁止することができる。既に書き込まれているFlash Cookieは、Webサイトの記憶領域設定パネルから、削除や禁止、ディスク容量の調整などが行える。また、HTTP Cookieについてはブラウザの設定で削除できる。

最後に、「ActionScript 3.0でFlash Cookieを利用する」で作成したプログラムを、HTTP CookieとFlash Cookieとで同期させるように変更してみたので、そのソースコードを以下に示しておく。赤字は前回からの修正箇所となる(クラス名などは除く)。使用する際は、HTMLのhead内に、

<script language="JavaScript" type="text/javascript"> function getCookie() { return document.cookie; } function setCookie(cookie) { document.cookie = cookie; } </script>

とJavaScriptのコードを記述しておくこと。

SyncCookie.as

// SyncCookie by nox, 2009.8.18 package { import flash.display.Sprite; import flash.text.* import flash.events.*; import flash.net.SharedObject; import flash.net.SharedObjectFlushStatus; import flash.external.ExternalInterface; [SWF(backgroundColor="0xffffff", width="300", height="100", framerate="30")] public class SyncCookie extends Sprite { [Embed(systemFont='MS P明朝', fontName='myFont', mimeType='application/x-font', unicodeRange='U+0030-U+0039,U+003F,U+2026,U+3044,U+304A-U+304B,\ U+304E,U+3053,U+3055,U+3057,U+3059,U+3066-U+3067,\ U+306A,U+306D-U+306F,U+307E,U+3081,U+3088-U+3089,\ U+308B,U+3092,U+4F1A,U+521D,U+56DE,U+62D2,U+72ED,\ U+76EE,U+79C1,U+7D76' )] private static const myFont:Class; private var textFormat:TextFormat = new TextFormat(); private var textField:TextField = new TextField(); private var mySharedObject:SharedObject; private function InputChar(event:KeyboardEvent):void { if (event.keyCode == 27) mySharedObject.clear(); textField.text = "さよなら…"; } public function SyncCookie() { textFormat.color = 0x000000; textFormat.size = 30; textFormat.font = "myFont"; textFormat.align = "center"; textField.defaultTextFormat = textFormat; textField.antiAliasType = flash.text.AntiAliasType.ADVANCED; textField.autoSize = TextFieldAutoSize.CENTER; textField.selectable = true; textField.embedFonts = true; var str:String; var count:int = 1; var allcookies:String = ExternalInterface.call("getCookie").toString(); var pos:int = allcookies.indexOf("SyncCookie="); if (pos != -1) { var start:int = pos + 11; var end:int = allcookies.indexOf(";", start); if (end == -1) end = allcookies.length; count = int(allcookies.substring(start, end)); mySharedObject = SharedObject.getLocal("SyncCookie"); mySharedObject.data.count = ++count; str = "お会いするのは\n"; str += count.toString(); str += "回目ですね"; textField.text = str; } else { try { mySharedObject = SharedObject.getLocal("SyncCookie"); var flushStatus:String = mySharedObject.flush(); if (flushStatus == SharedObjectFlushStatus.FLUSHED) { if (mySharedObject.data.count) { mySharedObject.data.count += 1; count = mySharedObject.data.count; str = "お会いするのは\n"; str += mySharedObject.data.count.toString(); str += "回目ですね"; textField.text = str; } else { mySharedObject.data.count = 1; textField.text = "初めてお会いしますね"; } } else { textField.text = "ここは狭すぎます…"; } } catch (e:Error) { textField.text = "私を拒絶するのですか?"; } } ExternalInterface.call("setCookie", "SyncCookie=" + count.toString()); textField.x = stage.stageWidth / 2 - textField.textWidth / 2; textField.y = stage.stageHeight / 2 - textField.textHeight / 2; stage.addEventListener(KeyboardEvent.KEY_DOWN, InputChar); addChild(textField); } } }

0 コメント: