1. 程式人生 > >07+. Django使用者登入驗證系統和登入登出

07+. Django使用者登入驗證系統和登入登出

碼農故事多微信公眾號二維碼
開啟微信掃一掃,關注微信公眾號【資料與演算法聯盟】

轉載請註明出處:http://blog.csdn.net/gamer_gyt
博主微博:http://weibo.com/234654758
Github:https://github.com/thinkgamer

寫在前邊的話

一直以來對Django的使用者許可權登入保護模稜兩可,最近由於在做一個django的專案,其中涉及到使用者的許可權登入保護,所以算是有些清楚了,總結下來,給還在模稜兩可的你閱讀。
附上我最近一直在commit的github地址:https://github.com/Thinkgamer/CSMarket

環境說明

Django:1.10
Python:3.5

使用者登入驗證

1:前提說明

    以下所談到的使用者登入驗證給予擴充套件Django 內建的User模型,以AbstractUser方式擴充套件User模型,Django中的使用者擴充套件的兩種方式可參考:http://blog.csdn.net/gamer_gyt/article/details/50499653
     以下程式碼為上邊給的github地址中的例項,抽取其中使用者驗證為例。

2:以AbstractUser方式擴充套件內建User

models.py:

from django.db import models
from
django.contrib.auth.models import AbstractUser # Create your models here. class User(AbstractUser): # 手機號 user_phone = models.CharField(blank=True, verbose_name='電話', max_length=11) #判斷是否是認證通過的使用者 user_isValid=models.BooleanField(blank=True,default=False) def __unicode__(self)
:
return self.user.username

admin.py:

from django.contrib import admin
from logre.models import User
admin.site.register(User)

3:authenticate 進行使用者驗證

    提供了使用者認證,即驗證使用者名稱以及密碼是否正確。一般需要username password兩個關鍵字引數。
    如果認證資訊有效,會返回一個 User 物件。authenticate()會在User 物件上設定一個屬性標識那種認證後端認證了該使用者,且該資訊在後面的登入過程中是需要的。當我們試圖登陸一個從資料庫中直接取出來不經過authenticate()的User物件會報錯的!!

user = authentica(username=’someone’,password=’somepassword’)

那麼使用者登入函式該怎麼寫呢?
views.py

#使用者登入
@csrf_exempt
def login(request):
    if request.method=='POST':
        uname=request.POST.get('username')
        pwd=request.POST.get('passwd')
        user = authenticate(username=uname,password=pwd)
        if user is not None:
            auth_login(request, user)
            # 更新最後登入時間
            now_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
            user.last_login=now_time
            user.save()
            return HttpResponseRedirect(referer)
        else:
            return render_to_response('login.html',{
                'error': '郵箱或者密碼不正確',
                'user_name': uname,
                'user_pwd': pwd,
            })
    else:
            return render_to_response('login.html',{})

注意事項:這裡的authentica函式只能接受username和password,因為我在測試email的時候不好使(如果恰巧你看到了這裡,並且驗證可以用email和password驗證的話,請留言)

AbstractUser擴充套件的User模型,在資料庫中密碼儲存形式是經過轉化的,所以我們並不能直接操作密碼,幸好django提供了專門的函式來修改密碼。

set_password 函式

eg:(由於我專案還沒更新到這一步,所以這裡就舉這樣一個簡單的例子)

>>> from django.contrib.auth.models import User 
>>> u = User.objects.get(username='john')
>>> u.set_password('new password') 
>>> u.save()

4:Permission

Django的auth系統提供了模型級的許可權控制, 即可以檢查使用者是否對某個資料表擁有增(add), 改(change), 刪(delete)許可權。

auth系統無法提供物件級的許可權控制, 即檢查使用者是否對資料表中某條記錄擁有增改刪的許可權。如果需要物件級許可權控制可以使用django-guardian。

假設在部落格系統中有一張article資料表管理博文, auth可以檢查某個使用者是否擁有對所有博文的管理許可權, 但無法檢查使用者對某一篇博文是否擁有管理許可權

user.has_perm方法用於檢查使用者是否擁有操作某個模型的許可權

eg:

user.has_perm('blog.add_article')
user.has_perm('blog.change_article')
user.has_perm('blog.delete_article')

如果要新增許可權的話,我們可以在後臺管理中自己新增,當然也可以使用以下方法新增

user.user_permissions.add()

刪除許可權:

user.user_permissions.delete()

清空許可權

user.user_permissions.clear()

使用者擁有他所在使用者組的許可權, 使用使用者組管理許可權是一個更方便的方法。Group中包含多對多欄位permissions, 在資料庫中由auth_group_permissions資料表維護。

新增許可權

group.permissions.add(permission)

刪除許可權

group.permissions.delete(permission)

清空許可權

group.permissions.clear()

使用者登入和登出

1:Http請求和迴應

2:使用者登入

該函式接受一個HttpRequest物件,以及一個認證了的User物件
此函式使用django的session框架給某個已認證的使用者附加上session id等資訊。

其實在我們上邊的views.py函式中也有看到就是 auth_login(request,user)
前提條件是擴充套件django的User使用者模型,使用時需要匯入django的login

from django.contrib.auth import login as auth_login

PS:我這裡as為auth_login是因為我的views函式為login,否則會重名,會出現錯誤
使用:

 uname=request.POST.get('username')
 pwd=request.POST.get('passwd')
 user = authenticate(username=uname,password=pwd)
 if user is not None:
    auth_login(request, user)

3:使用者登出

logout:該函式接受一個HttpRequest物件,無返回值。當呼叫該函式時,當前請求的session資訊會全部清除。該使用者即使沒有登入,使用該函式也不會報錯

from django.contrib.auth import logout as auth_logout
def logout(request):
    auth_logout(request)
    return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))

4:登入之後保持會話狀態

在其登入之後會將使用者資訊儲存在request中,那麼我們我進行一個views 函式前,可以先判斷下request.user是否存在,如存在將資料傳遞給返回前端,如果不存在我們也可以新增一些其他的邏輯。

def all(request):
    if request.user.is_authenticated:
        user_name=request.user
    else:
        user_name=''
    return render(request, 'news.html', {
        'user_name': user_name,
    })

5:如何記錄登入前的來源頁面

這裡我們使用的是:

request.META[‘HTTP_REFERER’]

大概實現的思路是:在login函式內宣告一個全域性變數referer,在不是發生post請求的時候記錄下來源頁面賦值給referer,在是發生post請求後返回到原頁面。程式碼如下:

#使用者登入
@csrf_exempt
def login(request):
    global referer
    if request.method=='POST':
        ...
        return HttpResponseRedirect(referer)
    else:
        try:
            referer = request.META['HTTP_REFERER']  # 獲取網頁訪問來源
        except:
            pass
        finally:
            return render_to_response('login.html',{})

總結

    其實Django本身的使用者驗證系統和登入登出功能是十分強大的,在開發過程中如果能利用好這些技術點,必然會節約很多我們的開發時間。