dorapon2000’s diary

忘備録的な。セキュリティとかネットワークすきです。

facebookのHTTPヘッダを読む

前回はtwitterのHTTTPヘッダを読んだので、今回はfacebookを読んでいく。前回とカブる部分は飛ばす。

dorapon2000.hatenablog.com

ヘッダ全体

$ curl -I -XGET https://www.facebook.com/
HTTP/2 200
vary: Accept-Encoding
pragma: no-cache
cache-control: private, no-cache, no-store, must-revalidate
expires: Sat, 01 Jan 2000 00:00:00 GMT
set-cookie: fr=XXXX; expires=Tue, 02-Feb-2021 11:33:15 GMT; Max-Age=7775999; path=/; domain=.facebook.com; secure; httponly
set-cookie: sb=XXXX; expires=Fri, 04-Nov-2022 11:33:16 GMT; Max-Age=63072000; path=/; domain=.facebook.com; secure; httponly
strict-transport-security: max-age=15552000; preload
x-content-type-options: nosniff
x-xss-protection: 0
x-frame-options: DENY
content-type: text/html; charset="utf-8"
x-fb-debug: XXXX
date: Wed, 04 Nov 2020 11:33:16 GMT
alt-svc: h3-29=":443"; ma=3600,h3-27=":443"; ma=3600

Vary

vary: Accept-Encoding

同一オリジンで同一ファイルへのアクセスだとしても、Accept-Encodingヘッダが異なる場合は別のファイルとして認識してキャッシュしないという意味。ブラウザとサーバの間にキャッシュサーバがあるとき、Varyヘッダを指定されたものは異なるファイルとしてキャッシュされる。

x-fb-debug

Debugging - グラフAPI - ドキュメンテーション - Facebook for Developers

名前の通り、Facebookデバッグのために利用されると説明されている。

Alt-Svc

alt-svc: h3-29=":443"; ma=3600,h3-27=":443"; ma=3600

HTTP/3のdraft29で同じドメインの443ポートでもアクセスできるということを知らせている。同様にh3-27でも。maはmax-ageの略でalt-svcを有効にする時間。

ドメインを指定する場合は次のようになる。

Alt-Svc: h2="alt.example.com:443", h2=":443"

実際にHTTP3でも通信できるか確認してみた。HTTP3の通信には以下のサイトを参考にした。

HTTP/3 対応の curl を作る - Qiita

❯ docker run --rm keioni/curl-http3 curl -Iv --http3 https://www.facebook.com
略
HTTP/3 200
vary: Accept-Encoding
pragma: no-cache
cache-control: private, no-cache, no-store, must-revalidate
expires: Sat, 01 Jan 2000 00:00:00 GMT
set-cookie: fr=XXXX; expires=Tue, 02-Feb-2021 13:26:39 GMT; Max-Age=7775999; path=/; domain=.facebook.com; secure; httponly
set-cookie: sb=XXXX; expires=Fri, 04-Nov-2022 13:26:40 GMT; Max-Age=63072000; path=/; domain=.facebook.com; secure; httponly
strict-transport-security: max-age=15552000; preload
x-content-type-options: nosniff
x-xss-protection: 0
x-frame-options: DENY
content-type: text/html; charset="utf-8"
x-fb-debug: XXXX
date: Wed, 04 Nov 2020 13:26:40 GMT
alt-svc: h3-29=":443"; ma=3600,h3-27=":443"; ma=3600

ちゃんとできている。HTTP/3にしてもヘッダは変わっていない。alt-svcで提案されるh3の片方は消えるのかと思ったけれど、そんなことはなかった。

おわりに

twitterとは同じ部分も違う部分もあった。

twitterではCSPが書かれていたがfacebookにはヘッダすらなかった。CSPを丁寧に書くとヘッダが膨らむためケアしたのかもしれない。一方、X-Content-Type-Options: nosniffX-Frame-Options: DENYはどちらにも存在した。こちらのほうがセキュリティ的な重要度が高いとどちらも認識しているのだと思う。

googleはどうだろう。次はgoogleのヘッダを見てみたい。

参考

HTTP Varyヘッダについて | Rの技術メモ

Fastly で Varyヘッダーを活用する - Qiita

twitterのHTTPヘッダを読む

HTTPヘッダを雰囲気で読んでしまっている。実際にどんなヘッダが使われていて、どのように使われているか調べてみるため、twitterのHTTPヘッダをMDN Web docsと照らし合わせながら1つずつ見てみた。セキュリティ的に公開してはいけなさそうな部分はXXXXとしている。

ヘッダ全体

$ curl -I -XGET https://twitter.com/
HTTP/2 200
cache-control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0
content-security-policy: connect-src 'self' blob: https://*.giphy.com https://*.pscp.tv https://*.video.pscp.tv 省略 ; default-src 'self'; form-action 'self' https://twitter.com 省略; font-src 'self' https://*.twimg.com; frame-src 'self' https://twitter.com 省略 ; img-src 'self' blob: data: https://*.cdn.twitter.com 省略; manifest-src 'self'; media-src 'self' blob: 省略; object-src 'none'; script-src 'self' 'unsafe-inline' https://*.twimg.com 省略 'nonce-MThhNzMwYjItNmI2ZS00YmNiLTgyNjctYzNhNDJmNjhmNTE0'; style-src 'self' 'unsafe-inline' https://*.twimg.com; worker-src 'self' blob:; report-uri https://twitter.com/i/csp_report?a=O5RXE%3D%3D%3D&ro=false
content-type: text/html; charset=utf-8
cross-origin-opener-policy: same-origin
date: Tue, 03 Nov 2020 13:37:45 GMT
expiry: Tue, 31 Mar 1981 05:00:00 GMT
last-modified: Tue, 03 Nov 2020 13:37:45 GMT
pragma: no-cache
server: tsa_m
set-cookie: personalization_id="XXXX"; Max-Age=63072000; Expires=Thu, 03 Nov 2022 13:37:45 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
set-cookie: guest_id=XXXX; Max-Age=63072000; Expires=Thu, 03 Nov 2022 13:37:45 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
strict-transport-security: max-age=631138519
x-connection-hash: XXX
x-content-type-options: nosniff
x-frame-options: DENY
x-powered-by: Express
x-response-time: 155
x-xss-protection: 0

Cache-Control

cache-control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0

no-storeはキャッシュをしないことを意味する。twitterのような常に情報が流動的なサイトはno-storeにする。

良い例:

Cache-Control: no-store

no-store以外にもいろいろと付いているが、キャッシュをしない場合はこれだけで十分だとMDN Web docsには書かれていた。

pre-check=0, post-check=0はIEのキャッシュ制御用らしい。*1

Content-Security-Policy

見やすく適宜改行した。

content-security-policy: 
  connect-src 'self' blob: https://*.giphy.com https://*.pscp.tv 省略 ; 
  default-src 'self'; 
  form-action 'self' https://twitter.com 省略; 
  font-src 'self' https://*.twimg.com; 
  frame-src 'self' https://twitter.com 省略 ; 
  img-src 'self' blob: data: https://*.cdn.twitter.com 省略; 
  manifest-src 'self'; 
  media-src 'self' blob: 省略; 
  object-src 'none'; 
  script-src 'self' 'unsafe-inline' https://*.twimg.com 省略 'nonce-MThhNzMwYjItNmI2ZS00YmNiLTgyNjctYzNhNDJmNjhmNTE0'; 
  style-src 'self' 'unsafe-inline' https://*.twimg.com; 
  worker-src 'self' blob:; 
  report-uri https://twitter.com/i/csp_report?a=O5RXE%3D%3D%3D&ro=false

特定のサイトのリソースしか読み込ませないためのヘッダ。リソースの種類ごとに細かく指定できる。report-uriはCSP(Content-Security-Policy)違反をしたときにブラウザが報告するURLが示されるが、非推奨でreport-toへと段階的に変更していくようだ。

Content-Type

content-type: text/html; charset=utf-8

おなじみコンテンツタイプヘッダ。charsetについて調べてみた。

仕組みを理解しており、可能であるなら、どのようなコンテンツであれHTTPヘッダーでエンコーディングを指定しましょう。しかし必ず同時に文書内での指定も行うべきです。

HTMLで文字エンコーディングを指定する

指定しないとどうなるかは実装次第のようで、必ず指定したほうがよいようだ。また、<meta>タグにもcharsetが指定できるが、優先度はContent-Typeのcharsetのほうが高い。

Cross-Origin-Opener-Policy

cross-origin-opener-policy: same-origin

twitterから別のサイトを開いたときに、別のサイトがwindow.openerからtwitterのプロパティを読み込めてしまうのはセキュリティ上よろしくないため、それを許可しないという意味。詳しくは以下のサイトを参照。

asnokaze.hatenablog.com

Date

date: Tue, 03 Nov 2020 13:37:45 GMT

日付。禁止ヘッダーと言われ、ユーザーエージェントが自動挿入するヘッダで、アプリケーション側で特定の日付を指定したりはできない。

expiry???

expiry: Tue, 31 Mar 1981 05:00:00 GMT

有効期限を示すExpiresならあるが、expiryは謎。twitterが独自に利用しているヘッダ?expiresのtypoだとしても、Cache-Controlでno-storeが指定されているため、コンテンツがキャッシュされることはない。

Last-Modified

last-modified: Tue, 03 Nov 2020 13:37:45 GMT

オリジンがそのファイルを最後に更新したとする日時が入る。If-Modified-Sinceなどで利用される。

Pragma

pragma: no-cache

現在HTTP/1.0との広報互換性のために利用されるヘッダで、ここではCache-Control: no-storeと同じことを表している。おそらく未だHTTP/1.1対応すらしていないブラウザが一定数あるのだろう。

Server

server: tsa_m

レスポンスを返したサーバで動くソフトウェアを表している。詳細に書くと攻撃に利用される可能性があるため、あまり詳細に記述しないほうがよい。tsa_mが何のソフトウェアを表しているかはよくわからなかった。

Set-Cookie

見やすいように適宜改行した。

set-cookie: 
  personalization_id="XXXX"; 
  Max-Age=63072000; 
  Expires=Thu, 03 Nov 2022 13:37:45 GMT; 
  Path=/; 
  Domain=.twitter.com; 
  Secure; 
  SameSite=None

Cookieをセットしている。

  • personalization_idだけがCookie本体で、それ以外はCookieに関する制御をしている。
  • DomainとPathでtwitter.comとそのサブドメインの場合のみCookieを送信できるようにしている。
    • 殆どの場合Path=/。
    • /が少し分かりづらいが、/*という意味。
  • SecureによってHTTPSでないとCookieを送信できない。
  • SameSite=Noneはオリジンをまたいでクッキーを送信して良いこと表している。
    • Noneを指定する場合、Secureが必須。
    • CSRF攻撃の予防のためにSameSiteがあるわけだが、Noneでも大丈夫なのだろうか。

Strict-Transport-Security

strict-transport-security: max-age=631138519

HTTPではなくHTTPSを利用するように促すヘッダ。リダイレクトとは違い、ブラウザが改めてHTTPSとして接続し直す。

利用例はMDN Web docsで示されている例がわかりやすい。HTTPでリクエストが来たとき、HTTPSのリダイレクトが記述されたHTTPレスポンスを返すのは、暗号化されていないため悪意のあるサイトへリダイレクトするよう書き換えられる可能性がある(中間者攻撃)。だからHTTPではなく新しくHTTPSで接続し直してとだけ返信するStrict-Transport-Securityが有用。

x-connection-hash

x-connection-hash HTTP response header

twitterが独自に定義しているヘッダだと思われる。

X-Content-Type-Options

x-content-type-options: nosniff

Content-Typeで指定したMIMEをブラウザが書き換えてはいけないと指定している。MIME Confusion Attackという攻撃を防げる。詳しくは以下のサイトで。

mozsec-jp.hatenablog.jp

X-Frame-Options

x-frame-options: DENY

ページが<frame>や<iframe>、<embed>、<object>の中に表示することを禁止している。クリックジャッキング攻撃を防げる。

X-Powered-By

x-powered-by: Express

一部のソフトウェアで送信されるヘッダーのようで、送信したソフトウェアがExpressであることを表す。

X-Response-Time

x-response-time: 155

以下のサイトによると、リクエストがミドルウェアに来てから、ヘッダが書かれるまでの時間を記録している。twitter以外でも使われていた。

X-Response-Time HTTP response header

X-XSS-Protection

x-xss-protection: 0

XSSを検出しても何もしないことを意味している。CSPで代用でき、レガシーブラウザをサポートしない限りはなくてもよいヘッダーのようだった。

CORS セーフリストレスポンスヘッダー

twitterにあったHTTPヘッダーの中で以下のものはCORS セーフリストレスポンスヘッダーと呼ばれる。

  • Cache-Control
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

CORS(オリジン間リソース共有)によってオリジンをまたいでHTTPクエリがとんでも、これらのヘッダーは含ませてもよいとされる。逆に、SetCookieなどは含ませてはいけない。

最後に

調べてみて、どこまでが実用上必要で、どこまでがレガシーをサポートするためなのかがわかって勉強になった。別のサイトについても調べてみたい。

参考

Cross-Origin-Opener-Policyについて - ASnoKaze blog

キャッシュについて整理 - Qiita

CookieのDomainとPath属性の仕様について調べた話 - emahiro/b.log

HTMLで文字エンコーディングを指定する

【翻訳】Firefox における MIME Confusion Attack の防止 - Mozilla Security Blog 日本語版

HttpFoundationで画像の条件付きGETを実装してみる (Symfony Advent Calendar JP 2012 - Day 22) - k-holyのPHPとか諸々メモ

Perlのautovivificationをいろいろ実験

Modern Perlを読んでいたら、autovivificationという機能があるということを今更ながら知った。たいへん便利だ。。。癖が強いらしいので手を動かして挙動を確かめてみる。

autovivificationとは

my %users;
$users{Brad}{id} = 228;
$users{Jack}{id} = 229;

$users{Brad}はまだ定義されていない(undef)はずだが、$users{Brad}{id}で代入できている。これはperl$users{Brad}を自動生成しているからで、autovivificationと呼ぶ。

perldocにもしっかりと説明がある。 autovivification

実験

Perl 5.30.2で行った。

use Data::Dumper;

sub func_array {
    my @h = @_;
    return @h;
}

sub func_ref {
    my ($h) = @_;
    return $h;
}

{
    # ハッシュ
    my %h;
    $h{empty}{aaa} = 'CCC';
    $h{not_empty}{aaa} = 'ZZZ';
    if (undef $h{undeff}{aaa}) {}
    if (exists $h{exists}{aaa}) {}
    func_array($h{via_func}{aaa});
    warn Dumper(\%h);
}

{
    # ハッシュリファレンス
    my $h;
    $h->{empty}->{aaa} = 'CCC';
    $h->{not_empty}->{aaa} = 'ZZZ';
    if (undef $h->{undeff}->{aaa}) {}
    if (exists $h->{exists}->{aaa}) {}
    func_ref($h->{via_func}->{aaa});
    warn Dumper($h);
}

{
   # 宣言と代入が同じ場合
    my $h->{aaa}->{bbb} = 'CCC';
    warn Dumper($h);
}

出力結果

$VAR1 = {
          'exists' => {},
          'undeff' => {
                        'aaa' => undef
                      },
          'via_func' => {},
          'empty' => {
                       'aaa' => 'CCC'
                     },
          'not_empty' => {
                           'aaa' => 'ZZZ'
                         }
        };
$VAR1 = {
          'not_empty' => {
                           'aaa' => 'ZZZ'
                         },
          'empty' => {
                       'aaa' => 'CCC'
                     },
          'via_func' => {},
          'undeff' => {
                        'aaa' => undef
                      },
          'exists' => {}
        };
$VAR1 = {
          'aaa' => {
                     'bbb' => 'CCC'
                   }
        };
  • リファレンスであろうと、なかろうと、宣言と同時に代入しようとautovivificationはされた
  • 参考のQiitaの記事でも取り上げられているように、undef関数でもautovivificationされた
  • キーの存在確認をするexistsですらautovivificationされた
  • undefとexistsでは生成のされ方が少し違うので注意
  • 関数に存在しないキーで引数として渡す際にもautovivificationされたが、最後までは生成されなかった?

no autovivification

参考で上げているQiitaの記事ではautovivificationというプラグマモジュールでautovivificationをいい感じに無効化していたため、インストールして使ってみた。

$ cpanm autovivification
# この一行を先程のコードの先頭に追加
no autovivification;
# no autovivification qw/ fetch exists delete /;と同じ

出力結果

$VAR1 = {
          'empty' => {
                       'aaa' => 'CCC'
                     },
          'via_func' => {},
          'undeff' => {
                        'aaa' => undef
                      },
          'not_empty' => {
                           'aaa' => 'ZZZ'
                         }
        };
$VAR1 = {
          'undeff' => {
                        'aaa' => undef
                      },
          'empty' => {
                       'aaa' => 'CCC'
                     },
          'via_func' => {},
          'not_empty' => {
                           'aaa' => 'ZZZ'
                         }
        };
$VAR1 = {
          'aaa' => {
                     'bbb' => 'CCC'
                   }
        };

existsだけautovivificationが無効化された。metacpanに書かれているが、何も指定せずno autovivificationした場合、rvalueデリファレンス$h->{a}->{b}が右側)・exists・deleteでautovivificationが無効化されるようだ。storeを指定すればlvalueデリファレンス$h->{a}->{b}が左側)でも対応できる。

no autovivification qw/  fetch exists delete store /;

storeを指定すると上で示したコードは実行できないコードとなるので、適宜修正する必要がある。もし実行した場合、以下のようなエラーが出る。

Can't vivify reference at tmp.pl line 16.

参考

qiita.com

developer.hatenastaff.com

最近読んだ本の感想

半年近くブログを更新していないせいで広告が出てしまったため、最近読んだ本をネタに更新しておく。

読んだ本一覧

開発系

  • ドメイン駆動設計入門
  • カイゼン・ジャーニー
  • Effective Python第2版
  • 達人に学ぶDB設計徹底指南書
  • 達人に学ぶSQL徹底指南書第2版
  • ソフトウェア技法練習帳
  • 最強のCSS設計

それ以外

  • 予想どおりに不合理
  • 「ついやってしまう」体験のつくりかた

ドメイン駆動設計入門

現実世界の注目している領域をドメインと呼び、それをコードへ落とし込むためにどういう思想や設計が必要かがわかりやすく記載されている。

ドメイン駆動設計入門 ボトムアップでわかる! ドメイン駆動設計の基本 | 成瀬 允宣 |本 | 通販 | Amazon

中規模なモジュールを1から作るにはどうすればいいのか、自分には皆目検討がつかないなぁと思い購入。自分はオブジェクト指向というメリットを活かしきれてなかったと痛感した。デザインパターンは勉強してきたけれど、設計とは目的が違う。自分の経験の中で、『最初はこれでうまくいくと思ってた設計は柔軟性がなく、拡張してたら似てるロジックがいたるところに、、、じゃあどうすればよかったかなんて考えてもわからない。』なんてことがあったけど、答えはこの本の中に。

個人的に好きだったのはリポジトリリポジトリでDB依存な実装を隠せば複数DB扱えるし、テストもしやすいというのはそのとおりだと思う。ただ、トランザクションまで設計で扱うのはやりすぎて逆に複雑になりそうだと思った。また、ドメイン駆動設計を取り入れるにはチームの同意も必要。

カイゼン・ジャーニー

ストーリー形式にアジャイル開発について学べる本。

カイゼン・ジャーニー たった1人からはじめて、「越境」するチームをつくるまで | 市谷 聡啓, 新井 剛 |本 | 通販 | Amazon

とても読みやすかった。主人公の江島がアジャイルのツールを使いながら問題解決していくのは臨場感あって、雰囲気でしか知らなかったアジャイル開発がどういうものなのか理解できた。

Effective Python第2版

Pythonの知られざるチップが90項目も書かれている。第2版でpython3.8対応。

Effective Python 第2版 ―Pythonプログラムを改良する90項目 | Brett Slatkin, 石本 敦夫, 黒川 利明 |本 | 通販 | Amazon

実は初版も昔読んでいる。掲載されている項目数も増えてpython3.8にも対応しているとのことで購入(並べてみると2.5倍くらい厚い)。自分が初版の内容を忘れてるor当時理解できなかったこともあり、2回目でも十分学びがあった。python3.8で追加されたwalrus演算子(:=)で不要に変数のスコープを広げないテクニックを見て、pythonっぽいと感じたり、特殊メソッド駆使してOOPをするテクニックはそんなに頑張るのかとも思いつつわくわくした。特に「並行性と並列性」の章は気合が入っているように感じて、pythonにはGILという制約がある中、いろいろな並列・並行処理のやり方を紹介している。家宝にします。

達人に学ぶDB設計徹底指南書

標準的なDBの、物理設計、正規形の説明からパフォーマンス設計、アンチパターン、グレーノウハウなどを説明している。

達人に学ぶDB設計 徹底指南書 | ミック | 工学 | Kindleストア | Amazon

特定のDBに依存しない部分で設計のノウハウ解いている。もともとMySQL関係の本を買うつもりだったが、DBの共通部分で一旦勉強しておいたほうが良いと思い購入。アンチパターンとグレーノウハウで著者がどれくらいの頻度で現実に存在するのか言及していたり、INDEXを貼るレコード数やカーディナリティの具体的な目安は、応用する際の助けになると思った。

達人に学ぶSQL徹底指南書第2版

標準的なSQLを駆使して複雑なことをクエリ一発で解決しようという本。

達人に学ぶSQL徹底指南書 第2版 初級者で終わりたくないあなたへ | ミック | コンピュータ・IT | Kindleストア | Amazon

上の作者のSQLの本。DB設計の本は2012年発売と少し古いが、こちらは2018年なため新しい。基本的にORMを使うため生のSQLをコードに埋め込むことはあまりないが、複雑なSQLに興味があったため購入。この本のおかげで、どこまでがDBの一般的な機能なのかという線引きができた。例えば、複合インデックスを使う場合、WHERE句にはインデックスに定義した順番でカラムを指定する必要があるというのはMySQLの機能だと勝手に思っていたが、この本に書かれており、DB共通のやり方だと知った。また、ある程度、排中律や述語などの論理学をベースにすすめるため、厳密性もあっていい。

SQLを構築するのはパズルのようで面白かったが、そこまで複雑なことはSQLではなくプログラムにやらせそうとは思った。

ソフトウェア技法練習帳

ソフトウェアテストの演習を、同値分割法・境界値分析、デシジョンテーブル、状態遷移テストなどの方法を用いてこなしていく。

ソフトウェアテスト技法練習帳 ~知識を経験に変える40問~ | 梅津 正洋, 竹内 亜未, 伊藤 由貴, 浦山 さつき, 佐々木 千絵美, 高橋 理, 武田 春恵, 根本 紀之, 藤沢 耕助, 真鍋 俊之, 山岡 悠, 吉田 直史 | コンピュータ・IT | Kindleストア | Amazon

境界値を選んで終わりという雑なテストの知識しかなかったため、新しい知識を取り込んで行きたいと思い購入。それぞれの手法の説明は一切ないが、ググりながらで十分演習ができた。ただ、組み合わせテストのためにPictMasterというツールを紹介しているが、当方Excelが使えないためできる問題だけこなした。要件を確認することが答えに含まれていたり、実践的で経験になった。

最強のCSS設計

OOCSS、SMACSS、BEMなどのCSS設計をケーススタディ形式で学べる。

Amazon.co.jp: 最強のCSS設計 チーム開発を成功に導くケーススタディ eBook: 堀口 誠人: Kindleストア

本棚に積まれていた本をようやく読んだ。ストーリー形式で読みやすいしレイアウトもわかりやすい。ストーリーの若手役の人がする失敗は自分もしそうで、文量抑えめなのに良いポイントを抑えてくれてると思った。自分のCSSはBootstrapの構造を真似ているだけだったため、ここでいったんOOCSSの知識を学べてよかった。BEMを使う機会はおそらく当分ないが、知識として持っておきたかった。さくっとCSS分野を学べる自分にあっている本だった。

予想どおりに不合理

大量の実験(多くは著者自身が行った)や例をもとに、人間が以下に不合理な行動を繰り返しているかを説明する行動経済学の本。

予想どおりに不合理 行動経済学が明かす「あなたがそれを選ぶわけ」 | ダン アリエリー, 熊谷 淳子 | 産業研究 | Kindleストア | Amazon

この記事に列挙したなかで一番読んでよかった。この本は以下の広告から始まる。

  1. 59ドルのオンライン新聞購読
  2. 125ドルの印刷版新聞購読
  3. 125ドルのオンラインと印刷版新聞購読

2が意味不明と思いながら買うなら3つ目を選ぶ人は多いと思う。実際に学生を対象にした実験では多かった。しかし

  1. 59ドルのオンライン新聞購読
  2. 125ドルのオンラインと印刷版新聞購読

この2つだけになった途端に1を選ぶ人が多くなる。マーケティングの知識がまったくない自分にとっては冒頭からドキリとさせられた。こういう例が大量にあり、ビジネスに限らず様々なことに応用できそうだと感じた。各実験に対する参考文献がしっかり記載されている点もうれしい。

「ついやってしまう」体験のつくりかた

任天堂wiiの企画担当を務められていた方なりにUXを体系的にまとめた本。

「ついやってしまう」体験のつくりかた――人を動かす「直感・驚き・物語」のしくみ | 玉樹 真一郎 | 産業研究 | Kindleストア | Amazon

予想通りに不合理もそうだが、分厚い技術書ばかりだとモチベーションが保てないので息抜きに購入。UXについての知識は皆無なので手始めに良さそうだと思った。そして、スーパーマリオブラザーズのマリオにはヒゲがあるのか、帽子をかぶっているのか、ステージ1-1のマリオの初期位置が中央ではないのか、などはすべて理由があることを知った。この本の中で一番印象的だったのは、ゲームにギャンブル要素とユーザーの性格が出てしまう選択肢を入れることがユーザーの飽きない・成長する体験につながること。特にギャンブルは予想通りに不合理でも触れられている。