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.

Djangoフレームワークのユーザーモデルと認証

7,223 views

Published on

Djangoフレームワークの認証機能の紹介です。

Published in: Engineering
  • Hello! Get Your Professional Job-Winning Resume Here - Check our website! https://vk.cc/818RFv
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Djangoフレームワークのユーザーモデルと認証

  1. 1. Djangoフレームワークの ユーザーモデルと認証 PyConJP 2017 岡野 真也 (@tokibito)
  2. 2. お前誰よ? 岡野真也 (@tokibito) 株式会社オープンコレクター http://www.open-c.jp/ お仕事あればご相談ください 2
  3. 3. 今日話すこと 認証と認可について 前知識 『Djangoの認証機能』 認証機能の使い方 認証機能の仕組み 認証機能のカスタマイズ Djangoのバージョンは、1.11を前提としています。 3
  4. 4. 認証と認可について 4
  5. 5. Auth 5
  6. 6. Auth? 認証(Authentication) システムから見て、利用者が誰であるかを判別 して扱うこと この話をします 認可(Authorization) システム上で、利用者に閲覧や操作を許可する こと 権限を扱うこと この話はしません (hirokikyさんのセッションへ) 6
  7. 7. 認証の話に入る前に Webアプリケーションで認証を扱うための前知識 HTTPヘッダ Cookie セッション ざっくり説明 (省略) ブラウザ=ウェブブラウザ(ChromeとかIE) (省略) サーバー=HTTPサーバー 7
  8. 8. HTTPヘッダ HTTPでのリクエスト, レスポンスの先頭のほうに ある情報 ブラウザの画面上には表示されない ブラウザがコンテンツをよしなに扱うための情報 が詰まってる ブラウザの開発者ツールで確認できるよ 8
  9. 9. ブラウザとサーバーのやりと り 9
  10. 10. Cookie ブラウザにデータを保存できるところ キーと値のペアで保存 サーバーからのレスポンスでHTTPヘッダにSet- Cookieでデータを入れとくと、 ブラウザが保存し てくれる 保存されたデータは、ブラウザが次回リクエスト 時に Cookieヘッダでサーバーに送信される 10
  11. 11. ブラウザとのCookieのやりと り 11
  12. 12. セッション(HTTPセッション) ブラウザからの操作(ページ遷移)を 一連の流れ と して扱うこと セッションに紐付けて、サーバー側で認証情報な どを保持したりできる(セッションデータ) 12
  13. 13. セッションの仕組み(例) 1. ブラウザがサーバーへHTTPリクエスト 2. サーバー側でセッションIDを発行し、Set-Cookie ヘッダに含めてレスポンス 3. ブラウザはCookieデータとしてセッションIDを保 存 4. 次回以降、ブラウザのHTTPリクエストでCookie ヘッダでセッションIDをサーバーに送信 5. サーバーはセッションIDが一致すれば同一セッシ ョンとして扱う 13
  14. 14. セッションのやりとり 14
  15. 15. ここからは『Djangoの』話 15
  16. 16. Djangoのセッション機能 django.contrib.session (デフォルトで有効) Cookieでは sessionid キーでセッションIDを保持 SessionMiddlewareにてCookieのセッションIDと サーバー上のセッションIDを照合 サーバー上に保存されたセッションデータは、 request.session 辞書に復元される 認証データはここに格納します 16
  17. 17. Djangoのセッション 17
  18. 18. ここからDjangoの認証の話 18
  19. 19. まずは使い方から。 19
  20. 20. Djangoの認証機能の使い方 アプリケーションの有効化 設定 ユーザーの登録 ログイン、ログアウトのView Viewでユーザー情報を使う ログインが必要なViewを作る ユーザーに紐づくデータ API 20
  21. 21. アプリケーションの有効化 Djangoプロジェクトの settings.py の INSTALLED_APPSに django.contrib.auth を記述 デフォルトで有効 MIDDLEWAREに django.contrib.auth.middleware.AuthenticationMiddleware を記述 デフォルトで有効 manage.py migrate でユーザー情報を保存するテー ブルを作成 21
  22. 22. 設定 ログイン後のリダイレクト先の設定 settings.LOGIN_REDIRECT_URL ログアウト後のリダイレクト先の設定 settings.LOGOUT_REDIRECT_URL ログインページのURL設定 settings.LOGIN_URL 22
  23. 23. ユーザーの登録 管理者ユーザーの登録 manage.py スクリプトの createsuperuser コマン ド ./manage.py createsuepruser 一般ユーザーの登録 Djangoの管理画面から登録 Userモデルを操作して登録 23
  24. 24. 24
  25. 25. ログイン、ログアウトのView urls.py で django.contrib.auth.views.LoginView を使い ます。ログアウトは LogoutView です。 from django.conf.urls import url from django.contrib.auth.views import LoginView, LogoutView urlpatterns = [ url(r'^login$', LoginView.as_view(), name='login'), url(r'^logout$', LogoutView.as_view(), name='logout'), ] ログイン画面のデフォルトテンプレートパスは、 registration/login.html 25
  26. 26. Viewでユーザー情報を使う Viewでは request.user を参照します。 未認証時は、 AnonymousUser 、認証済みの場合は User のインスタンスとなります。 from django.http import HttpResponse def my_view(request): if request.user.is_authenticated: return HttpResponse("認証済みです: {}".format( request.user.username)) else: return HttpResponse("未認証です") 26
  27. 27. ログインが必要なViewを作る ログインを必須とするViewを作る場合は、 django.contrib.auth.decorators.login_required デコレ ータを使います。 from django.contrib.auth.decorators import login_required @login_required def secret_view(request): "認証が必要なView" 未認証時にアクセスすると、ログインURLへリダイレ クトされます。 27
  28. 28. ユーザーに紐づくデータ ユーザーに関連するデータを保存するモデルを定義す る場合は、ForeignKeyには settings.AUTH_USER_MODEL を指定します。 from django.db import models from django.conf import settings class Article(models.Model): author = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, ) ユーザーモデルは、 settings.AUTH_USER_MODEL で変更 できるためです。 28
  29. 29. API 認証機能に依存するアプリケーションを作る際には APIを使います。以下は、特定のユーザーでログイン させる例です。 from django.shortcuts import redirect from django.contrib.auth import get_user_model, login def my_view(request): UserModel = get_user_model() # ユーザーモデルの取得 user = UserModel.objects.get(pk=1) # pk=1のユーザーを取得 login(request, user) # 取得したユーザーでログインさせる return redirect('/') # リダイレクト その他API多数。詳しくは ドキュメント を参照。 29
  30. 30. 使い方はここまで。 30
  31. 31. Djangoの認証機能の仕組み 31
  32. 32. ログイン処理のサーバー側 ざっくり説明すると、 1. ユーザーの照合処理 1-1. ユーザー名でDBからユーザー情報を探す 1-2. パスワード照合 1-3. 有効かどうかチェック ここまでに失敗したらログイン画面再表示 2. セッションにユーザーIDと使用したバックエンド クラス名を保存 3. リダイレクトレスポンスを返す 32
  33. 33. ログイン処理の流れ 33
  34. 34. ユーザーの照合処理の詳細 settings.AUTHENTICATION_BACKENDSに列挙され たクラスが使われます django.contrib.auth.backends.ModelBackend (抜粋) class ModelBackend(object): def authenticate(self, request, username, password): """usernameでユーザー情報を取得 passwordが正しければUserオブジェクトを返す""" def get_user(self, user_id): """user_idと一致するUserオブジェクトを返す""" 34
  35. 35. ユーザー情報 django.contrib.auth.models.User (抜粋) class AbstractBaseUser(models.Model): password = models.CharField() class AbstractUser(AbstractBaseUser, PermissionsMixin): username = models.CharField() class User(AbstractUser): class Meta(AbstractUser.Meta): swappable = 'AUTH_USER_MODEL' Userモデルにusernameとpasswordを保持しています 35
  36. 36. セッションへの保存 認証に成功すると、ユーザー情報はセッションに保存 されます request.session["_auth_user_id"] = user.pk request.session["_auth_user_backend"] = '(バックエン ドクラス名)' セッション機能によりこのデータは、サーバー側で保 存されます。 36
  37. 37. 認証できました ここまでの処理: セッションにユーザーID(認証データ)が保持された ログイン処理が成功したのでリダイレクトされた 次は認証データを使う処理を見ていきます。 37
  38. 38. 認証データの参照 認証データを参照する処理は、次のような仕組みで動 作します。 1. AuthenticationMiddleware 1-1. request.sessionからユーザーIDと認証バック エンドクラス名を取り出す 1-2. バックエンドクラスでUserを取得 1-3. request.user にUserかAnonymousUserを代入 2. Viewで request.user を参照する 38
  39. 39. 認証データの参照 39
  40. 40. セキュリティTips 複数のブラウザで同じユーザーにて同時にログイ ンは可能。 パスワードを変更した場合は、変更処理をした セッション以外のログイン情報は無効化される パスワードの暗号化処理は、カスタマイズ可能。 デフォルトのアルゴリズムはPBKDF2。 40
  41. 41. 認証機能のカスタマイズ 41
  42. 42. よくある要求 ユーザー情報のカラムを増やしたい ユーザーモデルのカスタマイズ LDAPやAD認証など他の認証システム(照合のみ)と 連携したい バックエンド変更 OAuth(OpenID Connect)で外部の認証システムと 連携したい python-social-authを使うだけでOK もしくは、Viewを用意+バックエンド変更 42
  43. 43. カスタマイズのポイント ユーザーモデルの変更 認証バックエンドの変更 43
  44. 44. ユーザーモデルの変更 AbstractBaseUser を継承してモデルを定義する PK(ID)は必須 複合主キーは使えません。 class MyUser(AbstractBaseUser): identifier = models.CharField(max_length=40, unique=True ... USERNAME_FIELD = 'identifier' settings.AUTH_USER_MODEL にクラスを指定すると有効化 詳しくは ドキュメント を参照。 44
  45. 45. 認証バックエンドの変更 authenticateとget_userメソッドを持ったバックエン ドクラスを定義して使います。 class MyBackend(object): def authenticate(request, **credentials): "照合OKならUserを返す処理を書く" def get_user(self, user_id): "user_idと一致するUserオブジェクトを返す処理を書く" settings.AUTH_BACKENDS にクラスを指定すると有効化 詳しくは ドキュメント を参照。 45
  46. 46. まとめ 認証(Authentication)は、システムから見て、利用 者が誰であるかを判別して扱うこと Djangoの認証機能では、セッションにユーザー情 報を保持している Djangoの認証機能は、認証バックエンドでユーザ ーの照合、取得をしている ユーザーモデルや認証バックエンドはカスタマイ ズできる 46

×