溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Django中怎么實現(xiàn)一個用戶認(rèn)證系統(tǒng)

發(fā)布時間:2021-07-20 16:10:42 來源:億速云 閱讀:128 作者:Leah 欄目:開發(fā)技術(shù)

本篇文章為大家展示了Django中怎么實現(xiàn)一個用戶認(rèn)證系統(tǒng),內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。

你可以通過is_authenticated()來區(qū)分,例如:

if request.user.is_authenticated():
  # Do something for authenticated users.
else:
  # Do something for anonymous users.

登陸login

login()

登陸函數(shù),需要一個HttpRequest對象和一個User對象作參數(shù)。login()使用django的session框架,將User的id存儲在session中。

同時使用authenticate()和login():

from django.contrib.auth import authenticate, login
 
def my_view(request):
  username = request.POST['username']
  password = request.POST['password']
  user = authenticate(username=username, password=password)
  if user is not None:
    if user.is_active:
      login(request, user)
      # Redirect to a success page.
    else:
      # Return a 'disabled account' error message
  else:
    # Return an 'invalid login' error message.

如果不知道密碼,login方法:

user=MyUser.objects.get(...)
user.backend = 'django.contrib.auth.backends.ModelBackend'
login(request,user)

退出登錄logout

logout()

使用HttpRequest對象為參數(shù),無返回值。例如:

from django.contrib.auth import logout
def logout_view(request):
  logout(request)
  # Redirect to a success page.

限制訪問

The raw way

使用 request.user.is_authenticated()

再定向:

from django.shortcuts import redirect 
def my_view(request):
  if not request.user.is_authenticated():
    return redirect('/login/?next=%s' % request.path)
  # ...

或者:

from django.shortcuts import render
def my_view(request):
  if not request.user.is_authenticated():
    return render(request, 'myapp/login_error.html')
  # ...

使用裝飾器login_required

login_required([redirect_field_name=REDIRECT_FIELD_NAME, login_url=None]

from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
  ...

如果用戶未登錄,則重定向到 settings.LOGIN_URL,并將現(xiàn)在的url相對路徑構(gòu)成一個next做key的查詢字符對附加到 settings.LOGIN_URL后面去:

/accounts/login/?next=/polls/3/.

query字符對的key默認(rèn)為next,也可以自己命名:

from django.contrib.auth.decorators import login_required
@login_required(redirect_field_name='my_redirect_field')
def my_view(request):
  ...

也可以自己定義login_url:

from django.contrib.auth.decorators import login_required
@login_required(login_url='/accounts/login/')
def my_view(request):
  ...

urls.py中需定義:

(r'^accounts/login/$', 'django.contrib.auth.views.login'),

測試登錄用戶

例如,要檢測用戶的email:

def my_view(request):
  if not '@example.com' in request.user.email:
    return HttpResponse("You can't vote in this poll.")
  # ...

可以用裝飾器:

from django.contrib.auth.decorators import user_passes_test
def email_check(user):
  return '@example.com' in user.email
 
@user_passes_test(email_check)
def my_view(request):
  ...

也可以改變login_url:

@user_passes_test(email_check, login_url='/login/')
def my_view(request):
  ...

認(rèn)證Views

當(dāng)然,我們可以自己定義一些登陸,登出,密碼管理的view 函數(shù),而且也更加方便。

不過也可以學(xué)習(xí)下Django內(nèi)置的views。

Django沒有為認(rèn)證views提供缺省模板,however the template context is documented for each view below.

所有內(nèi)置views都返回一個TemplateResponse實例,可以讓你很方便的定制response數(shù)據(jù)。

https://github.com/django/django/blob/master/django/contrib/auth/views.py

多數(shù)的內(nèi)置認(rèn)證views都提供一個URL名稱以便使用。

login(request[, template_name, redirect_field_name, authentication_form,current_app,extra_context])

源碼:

def login(request, template_name='registration/login.html',
     redirect_field_name=REDIRECT_FIELD_NAME,
     authentication_form=AuthenticationForm,
     current_app=None, extra_context=None):
  """
  Displays the login form and handles the login action.
  """
  redirect_to = request.POST.get(redirect_field_name,
                  request.GET.get(redirect_field_name, ''))
 
  if request.method == "POST":
    form = authentication_form(request, data=request.POST)
    if form.is_valid():
 
      # Ensure the user-originating redirection url is safe.
      if not is_safe_url(url=redirect_to, host=request.get_host()):
        redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)
 
      # Okay, security check complete. Log the user in.
      auth_login(request, form.get_user())
 
      return HttpResponseRedirect(redirect_to)
  else:
    form = authentication_form(request)
 
  current_site = get_current_site(request)
 
  context = {
    'form': form,
    redirect_field_name: redirect_to,
    'site': current_site,
    'site_name': current_site.name,
  }
  if extra_context is not None:
    context.update(extra_context)
  return TemplateResponse(request, template_name, context,
              current_app=current_app)

URL name: login

參數(shù):

template_name: 默認(rèn)的登陸模板.默認(rèn)為registration/login.html.

redirect_field_name: 重定向的name,默認(rèn)為next.

authentication_form: 默認(rèn)Form. Defaults to AuthenticationForm.

current_app: A hint indicating which application contains the current view. See the namespaced URL resolution strategy for more information.

extra_context: 添加到默認(rèn)context data中的額外數(shù)據(jù),為字典。

django.contrib.auth.views.login does:

如果通過GET訪問, 將顯示登錄表單,可以將其內(nèi)容POST到相同的URL上。

如果通過POST訪問,它首先會嘗試登錄,如果成功,view就重定向到next指定的的鏈接。如果next 未設(shè)置,則重定向到settings.LOGIN_REDIRECT_URL(一般缺省值為accounts/profile/)。如果登錄失敗,則再次顯示登錄表單。

需要用戶自己來提供login的html模板,缺省是registration/login.html 。這個模板將傳遞4個模板上下文變量:

form: 一個表單對象AuthenticationForm.
next: 登錄成功后的重定向鏈接,可以包含一個query string中。
site: 當(dāng)前網(wǎng)站,根據(jù) SITE_ID 設(shè)置。如果你并沒有安裝site框架,這個變量將設(shè)定為一個 RequestSite實例,它從當(dāng)前 HttpRequest中取得站點名和域名。
site_name: 是 site.name的一個別名。如果你沒有安裝site框架,它將會被設(shè)為 request.META['SERVER_NAME']的值。

如果你不想調(diào)用registration/login.html模板,你可以在URLconf中設(shè)定特定的view參數(shù)來傳遞template_name參數(shù)。

(r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'myapp/login.html'}),

你也可以自己指定重定向鏈接字段名,通過redirect_field_name 參數(shù)。默認(rèn)的字段名為next.

下面是registration/login.html 模板的原始狀態(tài),它假定你有一個base.html模板(其中有content block的定義。

{% extends "base.html" %}
 
{% block content %}
 
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
 
<form method="post" action="{% url 'django.contrib.auth.views.login' %}">
{% csrf_token %}
<table>
<tr>
  <td>{{ form.username.label_tag }}</td>
  <td>{{ form.username }}</td>
</tr>
<tr>
  <td>{{ form.password.label_tag }}</td>
  <td>{{ form.password }}</td>
</tr>
</table>
 
<input type="submit" value="login" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
{% endblock %}

如果自己定制認(rèn)證系統(tǒng),可以通過 authentication_form 參數(shù)把自定義的認(rèn)證表單傳給login view。該表單的__init__ 方法應(yīng)該有一個request 的參數(shù),并提供一個 get_user 方法來返回認(rèn)證后的User對象。

logout(request[, next_page, template_name, redirect_field_name, current_app,extra_context])

登出用戶.

URL name: logout

可選參數(shù):

next_page: 注銷后的重定向鏈接.

logout_then_login(request[, login_url, current_app, extra_context])

注銷用戶然后重定向到登錄鏈接.

可選參數(shù):

login_url: 登陸頁面的重定向鏈接,缺省值為 settings.LOGIN_URL。

password_change(request[, template_name, post_change_redirect,password_change_form,current_app, extra_context])

允許用戶修改密碼.

URL name: password_change

可選參數(shù) Optional arguments:

template_name: 模板名,缺省值為registration/password_change_form.html 。

post_change_redirect: 重定向鏈接。

password_change_form: 自定義的密碼修改表單,包括一個user 參數(shù)。缺省值為PasswordChangeForm.

password_change_done(request[, template_name,current_app, extra_context])

用戶修改密碼后的頁面.

URL name: password_change_done

可選參數(shù) Optional arguments:

template_name: 模板名稱,缺省為registration/password_change_done.html.

password_reset(request[, is_admin_site, template_name, email_template_name, password_reset_form, token_generator, post_reset_redirect, from_email, current_app, extra_context, html_email_template_name])

向用戶發(fā)送郵件,內(nèi)含一個一次性鏈接,來讓用戶重設(shè)密碼。

如果提供的郵箱不存在,則不會發(fā)送。

URL name: password_reset

可選參數(shù) Optional arguments:

template_name: 模板名稱,缺省值為registration/password_reset_form.html。

email_template_name: 用來生成帶充值鏈接email的模板名稱,缺省值為registration/password_reset_email.html。

subject_template_name: 用來生成郵件主題的模板名稱,缺省值為 registration/password_reset_subject.txt。

password_reset_form: 重設(shè)密碼的表單,缺省值為 PasswordResetForm.

token_generator: 檢查一次性鏈接的類實例,缺省值為default_token_generator, 其類為django.contrib.auth.tokens.PasswordResetTokenGenerator.

post_reset_redirect: 密碼重置后的重定向鏈接.

from_email: 郵件地址,缺省值為DEFAULT_FROM_EMAIL.

current_app: A hint indicating which application contains the current view. See the namespaced URL resolution strategy for more information.

extra_context: A dictionary of context data that will be added to the default context data passed to the template.

html_email_template_name: The full name of a template to use for generating a text/html multipart email with the password reset link. By default, HTML email is not sent.

示例: registration/password_reset_email.html (email內(nèi)容模板):

Someone asked for password reset for email {{ email }}. Follow the link below:
{{ protocol}}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}

password_reset_done(request[, template_name])

顯示用戶選擇發(fā)送密碼重置郵件后的頁面。如果 password_reset() view中沒有顯式指定post_reset_redirect鏈接時,則直接調(diào)用本view。

password_reset_confirm(request[, uidb36, token, template_name, token_generator,set_password_form, post_reset_redirect,current_app, extra_context])

顯示輸入新密碼的表單.

password_reset_complete(request[, template_name, current_app, extra_context])

重置密碼成功后的表單。

Helper functions
redirect_to_login(next[, login_url, redirect_field_name])

重定向到登錄頁面,登錄成功后的在重定向到另一鏈接。.

參數(shù):

next: 登錄成功后的鏈接.

login_url: 登陸頁面鏈接,默認(rèn)缺省值:settings.LOGIN_URL。

redirect_field_name: 重定向字段名稱,缺省值為next。

內(nèi)置表單 Built-in forms

class AdminPasswordChangeForm

admin后臺的用戶密碼修改表單

class AuthenticationForm

登錄表單。

方法confirm_login_allowed(user)

例如,允許所有的users登陸,不管is_active屬性:

from django.contrib.auth.forms import AuthenticationForm
 
class AuthenticationFormWithInactiveUsersOkay(AuthenticationForm):
  def confirm_login_allowed(self, user):
    pass

或者只允許活躍用戶登陸:

class PickyAuthenticationForm(AuthenticationForm):
  def confirm_login_allowed(self, user):
    if not user.is_active:
      raise forms.ValidationError(
        _("This account is inactive."),
        code='inactive',
      )
    if user.username.startswith('b'):
      raise forms.ValidationError(
        _("Sorry, accounts starting with 'b' aren't welcome here."),
        code='no_b_users',
      )

class PasswordChangeForm

修改密碼表單.

class PasswordResetForm

密碼重置表單.

class SetPasswordForm

密碼設(shè)置表單.

class UserChangeForm

admin后臺的用戶信息和權(quán)限修改表單.

class UserCreationForm

用戶創(chuàng)建表單.

模板中的認(rèn)證信息 Authentication data in templates

當(dāng)前登錄用戶及其權(quán)限可以在模板變量中取得,通過使用RequestContext.

Users

在渲染模板 RequestContext時,當(dāng)前的登錄用戶無論是User實例還是AnonymousUser 實例均保存在模板變量 {{ user }}:

{% if user.is_authenticated %}
  <p>Welcome, {{ user.username }}. Thanks for logging in.</p>
{% else %}
  <p>Welcome, new user. Please log in.</p>
{% endif %}

如果未使用 RequestContext,則此變量不存在。

使用RequestContext:

from django.shortcuts import render_to_response
from django.template import RequestContext
 
def some_view(request):
  # ...
  return render_to_response('my_template.html',
               my_data_dictionary,
               context_instance=RequestContext(request))

上述內(nèi)容就是Django中怎么實現(xiàn)一個用戶認(rèn)證系統(tǒng),你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI