Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
クロスオリジンでログイン状態を継続させるように見せるテクニック
Search
おdd
March 02, 2018
Programming
1
1k
クロスオリジンでログイン状態を継続させるように見せるテクニック
in YAPC::Okinawa(2018) 前夜祭LT
おdd
March 02, 2018
Tweet
Share
More Decks by おdd
See All by おdd
学歴マイノリティの皆様に贈る布石の打ち方のススメ
oddmutou
1
340
Other Decks in Programming
See All in Programming
git worktree × Claude Code × MCP ~生成AI時代の並列開発フロー~
hisuzuya
1
500
Systèmes distribués, pour le meilleur et pour le pire - BreizhCamp 2025 - Conférence
slecache
0
110
システム成長を止めない!本番無停止テーブル移行の全貌
sakawe_ee
1
140
20250628_非エンジニアがバイブコーディングしてみた
ponponmikankan
0
470
VS Code Update for GitHub Copilot
74th
1
420
ReadMoreTextView
fornewid
1
480
関数型まつり2025登壇資料「関数プログラミングと再帰」
taisontsukada
2
850
datadog dash 2025 LLM observability for reliability and stability
ivry_presentationmaterials
0
120
ruby.wasmで多人数リアルタイム通信ゲームを作ろう
lnit
2
280
What Spring Developers Should Know About Jakarta EE
ivargrimstad
0
290
Rubyでやりたい駆動開発 / Ruby driven development
chobishiba
1
460
地方に住むエンジニアの残酷な現実とキャリア論
ichimichi
5
1.4k
Featured
See All Featured
How STYLIGHT went responsive
nonsquared
100
5.6k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
233
17k
Gamification - CAS2011
davidbonilla
81
5.3k
The World Runs on Bad Software
bkeepers
PRO
69
11k
Product Roadmaps are Hard
iamctodd
PRO
54
11k
Intergalactic Javascript Robots from Outer Space
tanoku
271
27k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
107
19k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
229
22k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
46
9.6k
The Power of CSS Pseudo Elements
geoffreycrofte
77
5.8k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
31
1.2k
Measuring & Analyzing Core Web Vitals
bluesmoon
7
490
Transcript
クロスオリジンで ログイン状態を継続させる ( ようにみせる ) テクニック not SSO with perl(sledge)
and JS(jquery) 2018/03/02 YAPC::Okinawa 前夜祭 Nao Muto (@oddmutou)
自己紹介 氏名生年月日ハンドル 武藤 尚 Muto Nao (1996/06/25) Twitter 等 :
@oddmutou CPAN: MUTO 所属等 シーサー株式会社 社員 ( したらば掲示板, SesaaWiki , BoomAppGames , etc.) 東京デザインテクノロジーセンター専門学校 非常勤講師 東京通信大学 学生 ( 春から )( 第一期生予定 )( ネタ入学で差をつけろ )
とある新規サービス 仕様策定・設計等 他社競合 ? を見ると表示側はサブドメインを沢山つくってるしうちもそうしよう → 「そのほうがかっこよさそう ! 」( SEO
的にはどうなんかよくしらんけど) dev.to 流行ってるし CDN で爆速配信!目標の月間 ? 億 PV に耐えれるインフラも ! → 「やるぞ ! 」 (dev.to が話題になるあたりに始めて年内リリース済みの爆速開発 ) (インフラ設計も俺) SNS 連携 / 会員登録的な機能も作ろう → 「テンション上がってきた ! 」「まぢ卍」
雑な構成図 なんとか .sample.com user.sample.com 新規登録 / ログイン / ログアウト アカウント設定
アカウントへの通知なども - A.sample.com - B.sample.com - C.sample.com … 表示がメイン 裏側で使うようの何か .sample.com DB (記事データ等)や KVS (セッション等) ◦ 各 にはそれぞれ別のアプリが (マイクロサービス化的なことやってみたかったんです)
主なページは CDN でゴリゴリキャッシュさせるから静的 しかし右上にログイン状態を表示させたい ! github や twitter とかによくある,非ログイン時ならログインや新規登録へのリンクが,ロ グイン時ならアイコンがでるやつ。
→JS で取れるようにユーザー情報管理サーバーにログイン状態取得 API を作る →REST API? そんなのしらないヨ ということでセッションクッキーを見ちゃう $.ajax({ url:
‘https://user.sample.com’, type: 'GET', dataType: 'json', xhrFields: { withCredentials: true } }).done(function(response){ 以下略 「 xhrFields: {withCredentials: true} 」で cookie 送ってくれるのかーなるほどー
複数ドメイン間 (A.example.com → user.example.com) で API 叩くには Access- Control-Allow-Origin が必要というのはわかっていた。
また,今回はログイン状態を取るだけであるため,厳しく設定する必要もないので,「 * 」に する。 $self->r->header_out('Access-Control-Allow-Origin' => ‘*’);
> クロスオリジン要求をブロックしました : 同一生成元ポリシーによ り、 https://user.sample.com にあるリモートリソースの読み込みは拒否されます ( 理由 :
CORS ‘ ヘッダー Access-Control-Allow-Credentials’ ‘ は true’ である べき ) 。 ドメインが異なる API のときは「 Access-Control-Allow-Origin: * 」ってつけてれば良い ことは知っていたが, Cookie 送るときはまた別のものが要るらしい。 $self->r->header_out('Access-Control-Allow-Origin' => ‘*’); $self->r->header_out('Access-Control-Allow-Credentials' => "true");
> クロスオリジン要求をブロックしました : 同一生成元ポリシーにより https://user.example.com にあるリモートリソースの読み込みは拒否されます ( 理 由 :
CORS ‘ ヘッダー Access-Control-Allow-Origin’ ‘ が *’ である場合、認証情 報はサポートされない ) 。 Cookie 送るときは「 Access-Control-Allow-Origin: * 」だと怒られるらしいので,もう無 … 理やり 。 とりあえずこれで取得できて,超いい感じに表示できた。 $self->r->header_out('Access-Control-Allow-Origin' => $self->r->header_in('Origin')); $self->r->header_out('Access-Control-Allow-Credentials' => "true");
毎回 API 叩くのは負担になるからブラウザ側でキャッシュしたい ! →sessionStorage に保管する →sessionStorage は KVS なので出し入れ時に
JSON にデコード / エンコードする。 → 普段 SSR なサービスしか触ってないと知らないことだったけど,かんたん。 sessionStorage.setItem('login_status', JSON.stringify(response)); JSON.parse(sessionStorage.getItem('login_status')));
キャッシュクリアのタイミングどうする ? → sessionStorage なのでウィンドウ閉じればクリアされるが,それ以外に も, user.example.com でのログイン時・ログアウト時にキャッシュをクリアする必要があ る。 →
cookie のように「 *.example.com 」のようにスコープにワイルドカードを使いたいが, sessionStorage のスコープは「発生元のオリジン」 ( スキーム & ドメイン & ポート ) で固 定されており, user.example.com から A.example.com の sessionStorage を操作す ることはできない。
革命的発案 *.example.com な cookie に「ログイン状態の最終更新日時」を保管し,それを読んで sessionStorage を操作する &API を叩いて更新すればよい user.example.com
ログイン,ログアウト時に cookie を更新 $.cookie('update_time', 今の時間 , {path: '/', domain: '*.example.com'}); A.example.com ログイン,ログアウト時に cookie を更新 last_time = localStorage.getItem(‘last_time’;) time = $.cookie('update_time'); if (time > last_time) { localStorage のキャッシュを使う } else { API 叩く &localStorage のキャッシュを更新 localStorage.setItem(‘last_time’, 今の時間 ); } ↑ 「時間」の中身は端折りましたが,私は unix 秒 ( 整数値 ) を使いました。また jquery.cookie.js を使っていま
全く別ドメインのサービスでもユーザー情報使いたい ! → 敗北宣言 :iframe 使います user.example.com ログイン・ログアウトページ iframe 内の
hogehoge.com $.cookie('update_time', 今の時間 , {path: '/', domain: 'hogehoge.com'}); hogehoge.com 先ほどの A.example.com と同様に, cookie の update_time を見て localStorage のキャッシュを使うか, API 叩いて更新するかします。
ぼく「クロスオリジン,気が狂いそうです〜 ( 普段単純な SSR しかやらないので ) 」 先輩「広告やさんっぽいことやってるね〜」
似た話が別サービス(以下サービス A とします) で湧いてきた
ユーザーで独自ドメインが設定できるサービス A ↓ 記事ページにもログインしてコメントのフォームが欲しい ! ユーザーの独自ドメイン 適用ページ - トップページ -
記事ページ 等表示だけのページ & サーバー側でキャッシュも効いている 独自ドメイン 非適用ページ - コメントページ 等ログインして書き込みとかできるページ
サービス A において,静的ページでもログイン状態を表示したい場合は,セッション用の cookie が存在すれば API を都度叩く,という実装が既にあった。 ( 想定アクセス数的にキャッシュするほどでもないが,クローラーや一見さんの閲覧時に 無駄に
API 叩かれるのは怖いため。 ) ↓ 独自ドメインの場合はセッションが無いので,別途ログインするユーザーか見分ける印を 付ける必要がある。 そして歴史あるサービスであるため,深く弄りだすと年が暮れるので避けたい。
〜サービス A のログイン時の挙動〜 独自ドメインページ(ユーザーのドメイン)の「ログイン」リンクをクリック ↓ サービス A のデフォルトドメイン(弊社のドメイン) ↓ リダイレクト
弊社の複数サービスで使っているアカウントサーバー ↓ リダイレクト サービス A のデフォルトドメイン ↓ リダイレクト 独自ドメイン(「ログイン」リンクがあったページに戻る)
〜サービス A のログイン時の挙動〜 独自ドメインページ(ユーザーのドメイン)の「ログイン」リンクをクリック ↓ サービス A のデフォルトドメイン(弊社のドメイン) ↓ リダイレクト
弊社の複数サービスで使っているアカウントサーバー ↓ リダイレクト サービス A のデフォルトドメイン ↓ リダイレクト 独自ドメイン(「ログイン」リンクがあったページに戻る) ここにログインしていることを示す SessionStorage 保管する処理を追加
〜サービス A のログイン時の挙動〜 独自ドメインページ(ユーザーのドメイン)の「ログイン」リンクをクリック ↓ サービス A のデフォルトドメイン(弊社のドメイン) ↓ リダイレクト
弊社の複数サービスで使っているアカウントサーバー ↓ リダイレクト サービス A のデフォルトドメイン ↓ リダイレクト 独自ドメインで Cookie を操作 ↓ リダイレクト 独自ドメイン(「ログイン」リンクがあったページに戻る)
〜サービス A のログイン時の挙動〜 独自ドメインページ(ユーザーのドメイン)の「ログイン」リンクをクリック ↓ サービス A のデフォルトドメイン(弊社のドメイン) ↓ リダイレクト
弊社の複数サービスで使っているアカウントサーバー ↓ リダイレクト サービス A のデフォルトドメイン ↓ リダイレクト 独自ドメインで Cookie を操作 ↓ リダイレクト 独自ドメイン(「ログイン」リンクがあったページに戻る)
まとめ - クソにクソの上塗りをするのはいつも悔しい - どこでローカルに仕込むとか考えるのなんだかんだで楽しい! - Perl で単純に SSR なサービスしか書かないマン,たまにこういうことやると楽しい!