name: exercises-unix class: title, smokescreen, shelf, no-footer # 第09回 Unix演習<br><small>今回は無し</small> <div class=footnote> <small><small> 安心しろ(?)、このあとのAWS演習編が少し長めだ:-) </small></small> </div> --- name: exercises-aws class: title, smokescreen, shelf, no-footer # 第09回 AWS演習<br><small>Cookieを使う</small> <div class=footnote> <small><small> </small></small> </div> --- name: www-cookie class: title, smokescreen, shelf, no-footer # WWW技術: Cookie --- class: compact # 復習: HTTPはステートレスプロトコル - ステートレスとは「すべてのHTTPが独立」という意味です - TCPのような<B>状態という概念が無い</B> - ブラウザで<B>クリックするたびに新しくHTTPの通信を行います</B> - たとえ同じページを見る場合でも直前のクリックと今のクリックは別あつかいです - <B>同じユーザが連続アクセスしていることすらWWWサーバでは判断できません</B> <small> - 同じIPアドレスから連続してきていても同じユーザとは限らないし... - 例: 大学からのHTTPは区別できません。WWWサーバは1000人を一緒くた </small> - これがHTTP本来の仕様です - <B>これではログイン(=状態)すら実現できない</B>し、ショッピングサイトが作れないので... <br> -> 対策として考え出されたのがCookieという仕組みです --- class: compact, img-right # ブラウザを特定したいときはcookieを使う ![](https://1.bp.blogspot.com/-8_iInJA-VGo/UgSMUzbH8tI/AAAAAAAAXBk/rfI8OGB16n8/s800/sweets_cookie.png) - ブラウザ追跡技術の代表例が<B>Cookie</B> - <B>ブラウザの標準仕様</B> - <B>ブラウザの中に小さなファイル置き場(ストレージ)がある</B>と思って下さい <small> - 各サーバは、そこに小さな文字列を書きこめます。許可は不要で書きこめます - <B>ブラウザはサーバにアクセスする際、その文字列を送り返すという「お約束」</B>にしました - この文字列を追跡すればユーザの行動を追跡できるよね?ね? </small> --- class: compact, img-right # cookieの理屈(1) <div class=footnote> <small><small> (脚注) 本物のCookie文字列の例: sidts-CjEBPVxjSh4Ju8uC4obz5zgRbn4iCtdnNViQjVB0bQ0Ne7MSPk1ZlKidHj5ZpihY-iQvEAA </small></small> </div> ![](../images/www-cookie.png) - (a)ユーザがアクセスすると - (b)<B>WWWサーバからCookieが渡され</B>、 - (c)次回以降、ブラウザは、 そのサーバへアクセスする際に、 <B>そのCookie文字列をサーバへ送信</B>する <br> そういう<B>お約束(Protocol)</B>です --- class: compact, img-right # cookieの理屈(2) <div class=footnote> <small><small> (脚注1) 本物のCookie文字列の例: sidts-CjEBPVxjSh4Ju8uC4obz5zgRbn4iCtdnNViQjVB0bQ0Ne7MSPk1ZlKidHj5ZpihY-iQvEAA <br> (脚注2) ユーザを特定するには、Cookie以外の色々な情報を組み合わせないと無理ですが、やろうと思えば相当できるでしょう </small></small> </div> ![](../images/www-cookie-plural-users.png) - Coookie文字列をランダムに生成し - <B>ブラウザごとに異なるCookieを割当</B>ます - ブラウザから送り返されてくるCookieはブラウザごとに異なるので、 <B>どのブラウザからのアクセスかを特定</B>できます - ブラウザの特定 ≒ ユーザの特定 <small> - cookieだけで個人の特定は無理です - PCとスマートフォンで同じサイトを見たとしたら別人あつかいです - 逆に、つねにiPhoneでSafariを使うユーザは移動しようが(iphoneを)追跡されまくりです </small> --- class: compact,img-right # 例題: じゃんけんサーバにアクセスしてCookieを見てみる <div class=footnote> <small><small> (脚注) Google Chromeブラウザを使ってください or ブラウザのデバッグモードを呼び出してください </small></small> </div> ![](../images/chrome-devconsole-cookie.png) http://api.fml.org/janken-simple.html 1. 「じゃんけんぽん」をクリック 1. キーF12を押してChromeのデベロッパーツールを起動 1. URL直下の横並びメニューから「アプリケーション」を選択 1. 縦に現れるメニューの「Cookie」を選択 1. http://api.fml.orgをクリックするとcookieの値が読めます 1. リロードするとCookieの値も変わっていくことも確認してください <small> (このサーバは毎回ことなるCookieを与える仕様です) </small> --- name: exercises-aws class: title, smokescreen, shelf, no-footer # AWS演習<br><small>www.pyでクッキーをつける</small><br><small>- スケールアウトへ向けて -</small> <div class=footnote> <small><small> </small></small> </div> --- class: compact,img-right # はじめに - 第09-10回でやること - ![](../../exercise/images/sysbuild-plan-minimum.png) <small> - 最終課題(必須)では、きちんとスケールできるショッピングカートを作ってもらいます - そのためにはcookieを使う必要があります - 第09-10回では次の2つをします 1. <B>cookieをつけます(第09回=今回)</B> - 必須課題が2つあります(手順が2段階) <br> 両方とも必ずやってください 1. cookieを分散システムに保存する(第10回) </small> --- class: compact # 課題(必須): Cookieをつけてブラウザへ返事をする改造(1) <div class=footnote> <small><small> (脚注) 実質2行のお仕事:-) </small></small> </div> <small> - [課題] `_set_cookie()`メソッドを改造して、ブラウザにCookieを返すようにしてください - 動作確認 (TA/SAさんに確認してもらってください) - 改造したwww.pyを起動し、自分のブラウザでwww.pyへアクセスします <br> Developer Consoleでcookieを受け取れていることを見せてください - 仕様とヒント - self.cookieはdict型のように振る舞います - Cookieのキーは`_session`とします - Cookieの値は適当で良いです。なお模範解答は「UNIX TIME の使用」となります <br> ヒント: `time.time()`という関数がUNIX TIME (float型)を返します ``` def _set_cookie(self): # 次行がself.cookieに設定した値をsend_header()がHTTPヘッダとして送信します self.send_header("Set-Cookie", self.cookie.output(header="")) ``` </small> --- class: compact # 課題(必須): Cookieをつけてブラウザへ返事をする改造(2) <div class=footnote> <small><small> (脚注) これも前課題+実質2行のお仕事:-) </small></small> </div> - [課題] 連続したアクセスであれば同じCookieを使いつづける <small> - 前頁では毎回Cookieを更新しています。それでは追跡できません - <B>最初のアクセス時にだけ新しいCookie文字列を生成してブラウザに送り返して下さい</B> - ブラウザがCookieを送ってきた場合は、送られてきたCookieの値を使います (値を更新しません) - ヒント - 変数`self.cookie`はdict型のように扱えます - ブラウザが送ってきたcookie文字列を返すself._get_cookie() メソッドを使うと便利です:-) <br> メソッドの詳細は次頁以降の _get_cookie() と _set_cookie() の解説を参照 - 動作確認は前頁と同様です。Developer Consoleで動作をTA/SAさんに見せてください </small> ``` def _set_cookie(self): # 1. ブラウザがCookieを送ってきているか調べる # 2. 送ってきていないときにだけ、Cookieの値を設定する # 3. Set-Cookieフィールドを送信(ここは最初からあるので改造しない) self.send_header("Set-Cookie", self.cookie.output(header="")) ``` --- name: appendix-aws-www.py class: title, smokescreen, shelf, no-footer # 解説: www.pyの関数と改造について <div class=footnote> <small><small> </small></small> </div> --- class: compact # 解説: www.py内臓のCookie操作関数 <small> - コンストラクタ(`__init__()`)でCookieを操作するオブジェクトを生成し、 変数self.cookieに設定しています。 httpHandlerクラスの全メソッドで<B>self.cookieは利用できます</B> - 変数self.cookieはdict型のように扱えますが正確には違うので少し罠あり - 値を取り出すときは`self.cookie[ KEY ].value`のように書きます - www.pyには`_get_cookie()`と`_set_cookie()`というメソッドが用意されています - `_get_cookie()`は完成形ですが `_set_cookie()`は未完成です。 役割はメソッド名のとおり - `_get_cookie()`はブラウザから送られてきたCookie<B>文字列</B>(_sessionキーの値)を返します - `_set_cookie()`はSet-Cookie:ヘッダをつける部分だけ書いてあります(次頁を参照) - この関数を完成させる演習です </small> --- class: compact # 解説: _set_cookie()メソッド <small> ``` [www.pyに仕込まれているテンプレート] def _set_cookie(self): self.send_header("Set-Cookie", self.cookie.output(header='')) ``` - HTTPプロトコルの話 - サーバからクライアント(ブラウザ)には、 HTTPヘッダフィールド Set-Cookie でキーと値を送る - ヘッダの形式は`Set-Cookie: KEY=VALUE` - `self.send_header("Set-Cookie", self.cookie.output(header=''))`行がHTTPヘッダを送信しています。 この行の前で変数self.cookieに値を設定すれば、それが送信されます - 変数self.cookieにキーと値を設定するだけでOKです - `time.time()`はマイクロ秒単位でUNIX TIMEを生成してくれるので、それを使うと便利です <br> 値は 1706344607.2469046 のような浮動小数点です <br> 例: `self.cookie["_session"] = time.time()` </small> --- name: appendix-cookie-extension class: title, smokescreen, shelf, no-footer # 番外編: Cookieの応用 <div class=footnote> <small><small> </small></small> </div> --- class: compact, img-right # cookieを応用したレコメンデーションについて考える <div class=footnote> <small><small> (脚注) 紹介だけです。解説なしで通りすぎる予定。詳細は技術書を読んでくださいな </small></small> </div> - Cookieで追跡できているなら、こういう履歴がある - このユーザ(正確にはブラウザ)は、何回も異世界転生もののラノベ商品を見ている - サーバの思惑(1) ... わりと直球 - 異世界転生ものの新作ラノベ商品をおすすめしてみると買うかもしれん - 異世界転生もののBluRayもおすすめしてみよう、買うんじゃないか? - かっこよく言うと、これがPersonalized Recommendation - サーバの思惑(2) ... 少し高度な類推 - 他の似たような他ユーザの行動履歴からすると、(転生ではない)商品Xも買いそうだから、おすすめしてみよう。 何をもって「似ている」と判断するのしょうね? ここが、裏側で類推アルゴリズムをチューニングするエンジニアの腕の見せ所ですな - Amazonの履歴を元に、我が社のショッピングサイトでも買いそうなものを推めたい! - cookieだけでは無理なので、いろいろ組み合わせて類推ですね - だいたい、デフォルトでは、ドメインをまたぐcookieの利用は禁止 - てっとりばやいのは大手SNSとかに販売してもらうことだよね;-)