django.contirb.auth-認証
6771 ワード
まずmiddlewareの定義を見てみましょう.
authモジュールには、2つのmiddlewareがあります.AuthenticationMiddlewareとSessionAuthenticationMiddlewareです.
AuthenticationMiddlewareはrequestにuserプロパティを追加する責任を負います
AuthenticationMiddlewareは、sessionがユーザー情報を格納する必要があるため、session属性によって最初にチェックされることがわかります.
userプロパティの追加はget_に遅延されましたuser()関数にあります.SimpleLazyObjectは遅延技術である.
次のように定義されています.
セッション検証を担当します
userのget_を比較するsession_auth_方法とsessionの中のauth.HASH_SESSION_KEY属性は,ユーザのセッションが正しいか否かを判断する.
requestの中のuserオブジェクトについては、どのような属性があるか、get_を見る必要があります.user()関数の定義.
明らかにget_userメソッドはrequestに追加されました_cached_userプロパティ.キャッシュとして使用されます.
ユーザ認証にはデータベースを照会し,ユーザの情報を得る必要があるため,オーバーヘッドを減らす必要がある.
なお、このキャッシュは、同じrequestに対してのみ、すなわち、1つのviewでrequestに複数回アクセスする.userプロパティ.
httpリクエストのたびに新しいリクエストが表示されます.
次はauth.get_user()メソッドの定義、requestを深く理解する.userというオブジェクト:
まず、クライアントとサーバがセッションメカニズムを確立したと仮定します.このセッションのSESSION_KEY属性は、userのid番号です.
このセッションのBACKEND_SESSION_KEY属性は,どのバックグラウンド技術を用いてユーザ情報を取得するかを指定する.最後にbackendを使用します.get_user()はuserを取得します.満たされていない場合は、AnonymousUserオブジェクトを返します.
このuserを取得するプロセスには,まずクライアントとサービス側がsessionメカニズムを確立しなければならないという前提がある.では、このsessionメカニズムはどのように構築されていますか?
このセッションが確立されたプロセスはauthです.login関数では、
まず,ユーザ認証に関連するセッションがあるかどうかを判断し,ある場合はデータを空にし,ない場合は新規に作成する.
次にsessionの値:SESSION_と書きますKEY, BACKEND_SESSION_KEY, HASH_SESSION_KEY.
次に、ログイン時にauthを使用する一般的な方法について説明します.
一般的なコミットはPOST方式でコミットされ、authenticateメソッド検証が呼び出され、成功した後loginを使用してセッションが作成されます.
引き続きauthenticateの定義を見てみましょう.
backendsをポーリングし、backendのauthenticateメソッドを呼び出して認証します.
注意userのbackendプロパティは、ユーザーがどのbackend認証方式を使用しているかを示す後に更新されます.その値はlogin関数に格納され、セッションのBACKEND_に格納されます.SESSION_KEY属性にあります.
backendのauthenticateメソッドで返されるuserには、この属性はありません.
最後にログイン後のauthの使い方を説明します.ログイン時のauthの使い方を示しており,ログイン後にsessionメカニズムが確立される.したがってrequestのuser属性を直接取得することで,ユーザの情報や状態を判断することができる.
authモジュールには、2つのmiddlewareがあります.AuthenticationMiddlewareとSessionAuthenticationMiddlewareです.
AuthenticationMiddlewareはrequestにuserプロパティを追加する責任を負います
class AuthenticationMiddleware(object):
def process_request(self, request):
assert hasattr(request, 'session'), (
"The Django authentication middleware requires session middleware "
"to be installed. Edit your MIDDLEWARE_CLASSES setting to insert "
"'django.contrib.sessions.middleware.SessionMiddleware' before "
"'django.contrib.auth.middleware.AuthenticationMiddleware'."
)
request.user = SimpleLazyObject(lambda: get_user(request))
AuthenticationMiddlewareは、sessionがユーザー情報を格納する必要があるため、session属性によって最初にチェックされることがわかります.
userプロパティの追加はget_に遅延されましたuser()関数にあります.SimpleLazyObjectは遅延技術である.
次のように定義されています.
セッション検証を担当します
class SessionAuthenticationMiddleware(object):
"""
Middleware for invalidating a user's sessions that don't correspond to the
user's current session authentication hash (generated based on the user's
password for AbstractUser).
"""
def process_request(self, request):
user = request.user
if user and hasattr(user, 'get_session_auth_hash'):
session_hash = request.session.get(auth.HASH_SESSION_KEY)
session_hash_verified = session_hash and constant_time_compare(
session_hash,
user.get_session_auth_hash()
)
if not session_hash_verified:
auth.logout(request)
userのget_を比較するsession_auth_方法とsessionの中のauth.HASH_SESSION_KEY属性は,ユーザのセッションが正しいか否かを判断する.
requestの中のuserオブジェクトについては、どのような属性があるか、get_を見る必要があります.user()関数の定義.
def get_user(request):
if not hasattr(request, '_cached_user'):
request._cached_user = auth.get_user(request)
return request._cached_user
明らかにget_userメソッドはrequestに追加されました_cached_userプロパティ.キャッシュとして使用されます.
ユーザ認証にはデータベースを照会し,ユーザの情報を得る必要があるため,オーバーヘッドを減らす必要がある.
なお、このキャッシュは、同じrequestに対してのみ、すなわち、1つのviewでrequestに複数回アクセスする.userプロパティ.
httpリクエストのたびに新しいリクエストが表示されます.
次はauth.get_user()メソッドの定義、requestを深く理解する.userというオブジェクト:
def get_user(request):
"""
Returns the user model instance associated with the given request session.
If no user is retrieved an instance of `AnonymousUser` is returned.
"""
from .models import AnonymousUser
user = None
try:
user_id = request.session[SESSION_KEY]
backend_path = request.session[BACKEND_SESSION_KEY]
except KeyError:
pass
else:
if backend_path in settings.AUTHENTICATION_BACKENDS:
backend = load_backend(backend_path)
user = backend.get_user(user_id)
return user or AnonymousUser()
まず、クライアントとサーバがセッションメカニズムを確立したと仮定します.このセッションのSESSION_KEY属性は、userのid番号です.
このセッションのBACKEND_SESSION_KEY属性は,どのバックグラウンド技術を用いてユーザ情報を取得するかを指定する.最後にbackendを使用します.get_user()はuserを取得します.満たされていない場合は、AnonymousUserオブジェクトを返します.
このuserを取得するプロセスには,まずクライアントとサービス側がsessionメカニズムを確立しなければならないという前提がある.では、このsessionメカニズムはどのように構築されていますか?
このセッションが確立されたプロセスはauthです.login関数では、
def login(request, user):
"""
Persist a user id and a backend in the request. This way a user doesn't
have to reauthenticate on every request. Note that data set during
the anonymous session is retained when the user logs in.
"""
session_auth_hash = ''
if user is None:
user = request.user
if hasattr(user, 'get_session_auth_hash'):
session_auth_hash = user.get_session_auth_hash()
if SESSION_KEY in request.session:
if request.session[SESSION_KEY] != user.pk or (
session_auth_hash and
request.session.get(HASH_SESSION_KEY) != session_auth_hash):
# To avoid reusing another user's session, create a new, empty
# session if the existing session corresponds to a different
# authenticated user.
request.session.flush()
else:
request.session.cycle_key()
request.session[SESSION_KEY] = user.pk
request.session[BACKEND_SESSION_KEY] = user.backend
request.session[HASH_SESSION_KEY] = session_auth_hash
if hasattr(request, 'user'):
request.user = user
rotate_token(request)
まず,ユーザ認証に関連するセッションがあるかどうかを判断し,ある場合はデータを空にし,ない場合は新規に作成する.
次にsessionの値:SESSION_と書きますKEY, BACKEND_SESSION_KEY, HASH_SESSION_KEY.
次に、ログイン時にauthを使用する一般的な方法について説明します.
from django.contrib.auth import authenticate, login
def login_view(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
#
else: #
一般的なコミットはPOST方式でコミットされ、authenticateメソッド検証が呼び出され、成功した後loginを使用してセッションが作成されます.
引き続きauthenticateの定義を見てみましょう.
def authenticate(**credentials):
"""
If the given credentials are valid, return a User object.
"""
for backend in get_backends():
try:
inspect.getcallargs(backend.authenticate, **credentials)
except TypeError:
# This backend doesn't accept these credentials as arguments. Try the next one.
continue
try:
user = backend.authenticate(**credentials)
except PermissionDenied:
# This backend says to stop in our tracks - this user should not be allowed in at all.
return None
if user is None:
continue
# Annotate the user object with the path of the backend.
user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__)
return user
# The credentials supplied are invalid to all backends, fire signal
user_login_failed.send(sender=__name__,
credentials=_clean_credentials(credentials))
backendsをポーリングし、backendのauthenticateメソッドを呼び出して認証します.
注意userのbackendプロパティは、ユーザーがどのbackend認証方式を使用しているかを示す後に更新されます.その値はlogin関数に格納され、セッションのBACKEND_に格納されます.SESSION_KEY属性にあります.
backendのauthenticateメソッドで返されるuserには、この属性はありません.
最後にログイン後のauthの使い方を説明します.ログイン時のauthの使い方を示しており,ログイン後にsessionメカニズムが確立される.したがってrequestのuser属性を直接取得することで,ユーザの情報や状態を判断することができる.
def my_view(request):
if request.user.is_authenticated():
#
else:
#