Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

865 views

Published on

buddy-authのidentity実装をみてたときに、リクエストマップに対するmiddlewareの使い方でアハ体験した話

Published in: Technology
  • Be the first to comment

  • Be the first to like this

buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

  1. 1. buddyのユーザ認証周りのデータ構造 使われているデータの取り回しについてのお話 2017/11/17 clj-ebisu #1
  2. 2. 出演 {:company “Greative.GK” :name “Kazuhiro Hara” :twitter “@kara_d” :interest “SPA, WebVR, Clojure, Design research”}
  3. 3. Clojure / ClojureScript で Electronアプリケーションを 作るためのスタートキット / プラットホーム ● オープンソースにてGitHubにて公開 ● MITライセンス ● 現在のスター数 : 329 http://descjop.org/
  4. 4. 今日お話しすること
  5. 5. 今日お話しすること buddy-authのidentity実装をみてたときに、 リクエストマップに対するmiddlewareの使い方で アハ体験した話
  6. 6. buddyってなにさ、というあたりから
  7. 7. buddyについて buddy is a complete security library for clojure. With support for: ● authentication, authorization & access rules (ring/compojure extensions) ● secure hash functions (digest) ● password hashing algorithms (bcrypt, pbkdf2, scrypt) ● message/text signing (high level interface) ● signature & authentication (mac & digital signature) ● encryption (block, stream ciphers, nonces, salts) ● key derivation functions (kdf)
  8. 8. buddyのパッケージ ● buddy-core ● buddy-auth ● buddy-hashers ● buddy-sign
  9. 9. buddyのパッケージ ● buddy-core ● buddy-auth ⇦ 今日はこのあたりの話 ● buddy-hashers ● buddy-sign
  10. 10. ユーザの認証・認可を実装するとき、お世話に ● 認証スタイルも、Basic、セッション、トークン、JWS、JWEといろいろ ● 特定ルート以下に適用するとかも楽 (def access-rules {:pattern #"^/admin.*" :handler authenticated-user?}) (-> app-routes (wrap-access-rules {:rules [ access-rules]}) (wrap-authentication backend) (wrap-authorization backend) (wrap-session {:store (session-cookie/cookie-store {:key key}) :cookie-attrs attr :cookie-name name})
  11. 11. buddy-authを使った認証の一例 セッションベース
  12. 12. buddy-authを使った認証の一例(リクエスト編) 1. 認証対象のパスへアクセス( /admin とか) 2. セッションから認証済みかどうか確認 3. 認証済みであれば、リクエストマップへ :identity キーを追加 3.1. 必要な処理をして、レスポンスを返す 4. 認証済みでなければ、:unauthorized-handler を実行 4.1. エラー表示など (defn wrap-authentication [handler & backends] (fn [request] (if-let [authdata (authenticate-request request backends)] (handler (assoc request :identity authdata)) (handler request))))
  13. 13. buddy-authを使った認証の一例(ログイン編) 1. ログインフォームから、認証に必要な情報を送信 2. 認証に必要な情報を照会 3. 認証OKであれば :identity キーをセッションに書き込む 3.1. 適切な処理を行う、もしくはリダイレクト 3.2. identity のセッションへの書き込みは、自前で行う 4. 認証NGであれば、ログインフォームに戻るなどの処理をする (-> (redirect next) (assoc :session updated-session))
  14. 14. 認証されたリクエストかの確認 authenticated?関数でチェックができる やっていることはシンプル (defn authenticated-user? [request] (if (auth/authenticated? request) (accessrules/success) (accessrules/error))) (defn authenticated? [request] (boolean (:identity request)))
  15. 15. 更に、identityについて
  16. 16. identityには何が格納できる? よくあるサンプルでは「ユーザー名」 中身は、edn形式の {:identity :admin} になる そこで生まれる疑問、ユーザー名じゃないとだめなのか 結局、edn形式になるので、ednとして表現できるものならなんでもつっこめる
  17. 17. identityにマップを入れたらどうなる? :identityに {:username :user, :role :admin} を入れてみる cookieのセッション領域には、 H/XbI0K3JU9TGMoyoGN16Ud2q4n8paIavLMFO+PQcqtXd3PtBIh9jmkg04FvqFuDXSYBlCbYAfMu8GhzE9ZFYQ==--BxvDyxfR0dtzjBiZqVPihT ld/sLIYvI9hRycPtTQ1nM=などが入り、 中身は、{:identity {:username :user, :role :admin}} となる
  18. 18. identityに関数をつっこむと? :identity に、例えば (fn [a] (println a)) を入れてみる シリアライズに失敗してランタイムエラー java.lang.RuntimeException No reader function for tag object
  19. 19. identityの不思議さ 今まで使ってきたWebアプリケーションフレームワークのリクエスト情報の利用スタイルで は、リクエストオブジェクト的なものは、読みこんで利用するだけ public Result index() { String username = session("identity"); if(username != null) { return ok("Hello " + username); } else { return unauthorized("Oops, you are not connected"); } }
  20. 20. よくあるリクエスト情報の処理 リクエストは、専用のコンテキストオブジェクトなどに格納され、それがコントローラを通じ て、モデルなどで利用される request controller service model
  21. 21. リクエストデータとミドルウェアパターン 最初、Clojureを触ったときは、requestには手を触れなかったが(ミドルウェアは利用して いたものの)、変えるだけでなく、キーの追加もいいという驚き。 Middleware Patterns · ring-clojure/ring Wiki https://github.com/ring-clojure/ring/wiki/Middleware-Patterns request wrap-foo request wrap-bar request wrap-baz request
  22. 22. まとめ
  23. 23. ベルトコンベアのような認証プロセス requestをもらって、コントローラ受け取って処理をして、responseを返すというスタイルだ けでないやりかたに感銘を受けた。 個人的には、buddy-authのidentity実装には、Clojureで開発をしていく上でヒントになる と感じたものが見れた。 フラグを立てるところと、フラグに基づいた処理をするところは別でもいい 受け取ってたらい回しにして処理するしかないようなものも、ミドルウェアとして組み合わ せることで、独立性が高い実装が行える
  24. 24. こぼれ話
  25. 25. セッションの中身はどうなるのか?
  26. 26. セッションに書き込まれたidentityは信用できるか ring.middleware.session.cookie に実装がある ● HmacSHA256 ○ SHA-256で構築された、ハッシュメッセージ認証コードとして使用可能なキー付きハッシュアルゴリ ズムの一種 ● AES/CBC/PKCS5Padding ○ データ本体はAES暗号化
  27. 27. セッションの中を見る 開発側からは見れます 中身は、edn形式の {:identity :admin} になる (let [cookieStore (session-cookie/cookie-store {:key "d41d8cd98f00b204"}) cookie-read (session-store/read-session cookieStore "LcgrPJu3zE0/Pvd0cSFo29jE/IlLlwRAa6Jo99FCZF9WKoJj/5bOLbp8g2mAB585--QB0LJInHfO CBH8kUwSIcOnrWqq7Ldk6wcHwinX/Kqug=")] (println (str cookie-read)))
  28. 28. CookieStore本体は見れない ns-unmapされている 中身はこう (deftype CookieStore [secret-key] SessionStore (read-session [_ data] (if data (unseal secret-key data))) (write-session [_ _ data] (seal secret-key data)) (delete-session [_ _] (seal secret-key {}))) (ns-unmap *ns* '->CookieStore)
  29. 29. - END - ありがとうございました 2017/11/17 clj-ebisu #1

×