CocoaアプリでCookieを独自に管理する
CocoaのURL Loading Systemは通常、HTTP Cookieを自動的に管理してくれる。CookieはNSHTTPCookieというクラスにラップされ、NSHTTPCookieStorageというクラスがそれを溜め込んで自動的にどうこうしてくれる。しかし困るのは、CocoaのCookieはNSHTTPCookieStorageを使う限り全アプリで共通だということだ。URL Loading Systemを直接叩くアプリでなくても、ちょっとWebKitを使ってWebページを表示するだけのアプリでも同様である。Safariで何かのログイン状態をCookieが保持していたら、Thousandでもそのままログインしていたりする、つまりはそういうことで困るのだ*1。
では独自にCookieを管理したいときはどうすればいいのか。NSURLRequest に次のようなメソッドがある。
-(BOOL)HTTPShouldHandleCookies ;
デフォルトはYESで、その場合自動的にNSHTTPCookieStorageによるCookieの管理が行われる*2 *3。ので、これをNOにした上で自前でCookieの管理をすればいいはずである。NOにするにはNSMutableURLRequestを使う。
- (void)setHTTPShouldHandleCookies:(BOOL)handleCookies ;
次は自前でCookieの管理ってどうすればいいんだろうということになるが、NSHTTPCookieにあるメソッドである程度道筋がつく。
+ (NSArray *)cookiesWithResponseHeaderFields:(NSDictionary *)headerFields forURL:(NSURL *)theURL ; + (NSDictionary *)requestHeaderFieldsWithCookies:(NSArray *)cookies ;
NSHTTPURLResponseのヘッダーフィールドからCookieを生成したり、CookieからNSURLRequestのヘッダーフィールドへ値を設定したりはこれで出来る。そこでNSHTTPCookieを溜め込んだ上で、これらのメソッドを使っていろいろしてくれる、要は自前のNSHTTPCookieStorageっぽいものを作ってやることになる。
自前のNSHTTPCookieStorageは何をしなければならないか
ヘッダーフィールドとCookieのやりとりはこれで出来るとして、一番問題になりそうなのはURLに応じて適切なCookieを取り出してくることである。
ここを参考にして勉強してみた。
Studying HTTP: HTTP Cookies
http://www.studyinghttp.net/cookies
このとき、URLのドメインの後方に一致したCookieを送ることになる。この場合だったら、hoge.www.apple.comを含むURLには、3つ全てのCookieを送ることになるのかな。
次に、ドメインの中でさらにパスごとにCookieを持つことになる。
このとき、パスの前方に一致してより詳細なCookieが、ヘッダーフィールドを上書きする。…上書き?クッキーの持つキーバリューのペアのうち重複するものが上書きされるということかな。
よってドメインとパス、2段階でCookieを検索出来る仕組みが必要である。私はNSMutableDictionaryの入れ子でやってみた。
追記
間違えた。NSHTTPCookieはキーバリューにつき一つだからえーと、ドメイン、パス、名前で3段階で検索するときもある。同じ名前でパスが違うNSHTTPCookieは、パスがより詳細に一致するほうが優先される、と。よし。
他にしなければいけないこと
- 有効期限のチェック
- セキュアかどうかのチェック
- セッション限りだったら捨てる
まあここらへんは普通に出来そうだ。これでなんとか自前でCookieの管理が出来るのではないか?これから試してみる。