Vue結合Django-Rest-Frameword結合實現登錄認證(一)


作者:小土豆

博客園:https://www.cnblogs.com/HouJiao/

掘金:https://juejin.im/user/58c61b4361ff4b005d9e894d

微信公眾號:不知名寶藏程序媛(關注"不知名寶藏程序媛"免費領取前端電子書籍。文章公眾號首發,關注公眾號第一時間獲取最新文章。)

碼字不易,點贊鼓勵喲~

前言

最近需要做一個登錄認證的功能,所以想將整個的過程做一個記錄,方便以后回頭查看,同時希望給我遇到同樣問題的同學一些參考。

因為認證是后端的功能,所以我這個不專業的前端在實現這個功能的時候不會深究太多。所以在記錄的過程中沒有過多的原理,着重記錄實現過程和這個過程中遇到的問題以及解決方案。

如果對登錄這塊前后端流程原理不太懂的,可以先做一點功課,或者直接看我的整個操作和結果,看完之后會從結果和現象出發,在去理解學習登錄認證原理就會更容易。

初始的環境介紹

前端框架

框架:Vue
HTTP庫:axios

后端項目

后端框架:基於pythondjango框架
WEB API:rest-framework
服務器: centos
數據庫:PostgreSQL
python版本:2.7.5
django版本:1.10.1

關於后端數據庫的一些說明

數據庫使用的是PostgreSQL,並且已經對數據庫表進行了同步,命令為:python manage.py migrate

數據庫進行同步以后,會生成10相關的數據表。

需要關注的就是auth_user表這個表,它是django框架生成的用戶表,后面就使用這個表保存用戶的信息。

我們查看一下這個表結構。

表里面暫時沒有什么數據。

接着我們來創建一個用戶,用於后期的登錄測試:python manage.py createsuperuser

用戶創建成功,此時在去查詢數據表,就有一條用戶信息了。

接下來就是登錄驗證的實現了。

后端Django項目配置

Django登錄認證配置

首先我們需要在setting.py文件的INSTALLED_APPS配置登錄認證的APP

INSTALLED_APPS = [
    ...
    'rest_framework.authtoken'
]

設置全局的認證方案

接着在setting.py中配置全局身份認證方案。

# 設置全局身份認證方案
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',  # token認證
    )
}

數據庫同步

上面的配置完成需要進行數據庫同步:python manage.py migrate

在此查看數據庫:

發現會多出來一個名為authtoken_token的數據表,這個表就是和用戶認證相關的數據表。

簡單測試

我們已經配置好了全局的認證方式,那按道理來說,現在任意訪問后端的某個API就會出現為HTTP 401未經授權這樣的錯誤,那我們來試一試。

那結果發現請求還是可以正常發出。
這塊在網上搜索了很久,看到有網友說關於setting設置的全局身份認證方案配置有問題,正確的配置是

# 設置全局身份認證方案
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',  # token認證
    )
}

DEFAULT_PERMISSION_CLASSES是關於用戶的權限配置,如果沒有配置該項的話就是允許用戶無限制訪問,不管我們的請求是被認證或未認證的。

這塊可以看 👉官方文檔 的說明

那加上這個認證以后呢,在去請求前面的API


發現這次終於有反應了,服務器端返回了401,就是用戶認證失敗。

經過一陣思考后的再次測試

那接着我想起前面新增的IsAuthenticated授權配置,所以將setting進行了修改。

# 設置全局身份認證方案
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    # 'DEFAULT_AUTHENTICATION_CLASSES': (
    #     'rest_framework.authentication.TokenAuthentication',  # token認證
    # )
}

即注釋了全局的用戶認證,保留了權限認證,測試一下這個全局的授權配置會對請求產生什么影響。

我們發現這條API返回了403,也就是訪問的權限出現了問題。

那不管怎么樣,在單獨配置TokenAuthentication的情況下確實無法生效,而且官方文檔也明確說明:如果沒有配置DEFAULT_PERMISSION_CLASSES就是允許用戶無限制訪問,不管我們的請求是被認證或未認證的。

所以如果需要進行用戶認證,那必須的也配上權限驗證,用戶認證才會生效。

這個僅僅是自己的一個嘗試

后端Django項目實現登錄API

接着我們來實現后端的登錄接口

創建一個新的app

django-admin startapp userAuth

在views.py中編寫登錄邏輯

# -*- coding: utf-8 -*-
# Create your views here.

from django.contrib import auth

from rest_framework.permissions import AllowAny
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
from rest_framework.decorators import api_view, authentication_classes, permission_classes

@api_view(['POST'])
@permission_classes((AllowAny,))
@authentication_classes(())
def login(request):
    """登錄"""
    result = True
    errorInfo = u''
    detail = {}
    data = request.data
    username = data.get('username')
    password = data.get('password')
    
    # 調用django進行用戶認證 
    # 驗證成功 user返回<class 'django.contrib.auth.models.User'>
    # 驗證失敗 user返回None
    user = auth.authenticate(username=username, password=password)
    print "user",user
    if user == None:
        result = False
        errorInfo = u'用戶名或密碼錯誤'
        return Response({"result": result, "detail": detail, "errorInfo": errorInfo})
    
    # 用戶名和密碼驗證成功
    # 獲取用戶的token 如果沒有token ,表示時用戶首次登錄,則進行創建,並且返回token
    try:
        tokenObj = Token.objects.get(user_id=user.id)
    except Exception as e:
        # token 不存在 說明是首次登錄
        tokenObj = Token.objects.create(user=user, token=token)
    # 獲取token字符串
    token = tokenObj.key
    return Response({"result": result, "detail": {'token': token}, "errorInfo": errorInfo})

那登錄的簡單代碼邏輯就寫好了。

在這之前呢,我們先看下前面生成的關於用戶認證的數據表authtoken_token

暫時是沒有任何記錄,然后在產品的登錄界面輸入用戶名和密碼。

這里的用戶名和密碼就是前面使用python manage.py createsuperuser命令創建的admin賬戶

因為是首次登錄,因此為該用戶創建token,即authtoken_token會產生一條記錄。

這里給大家看一看我登錄成功以后的authtoken_token數據表。

前端關於登錄的邏輯處理

最后就是關於前端vue處的邏輯,我們先看一下登錄頁面的methods邏輯。

login: function(){
      axios.post(url, this.loginForm).then(response =>{
          const {result, detail, errorInfo}  = response.data;
          if(result == true){
              // 登錄成功
              // 設置token
              localStorage.setItem('token', detail.token);
              // 跳轉頁面
              this.$router.push('/certMake');
          }else{
              this.$message({
                  showClose: true,
                  message: errorInfo,
                  type: 'error'
              });
          }
      });
  }

可以看到登錄成功以后我使用localStoragetoken進行本地存儲。

接着我們需要在訪問其他API時將這個token設置到請求頭部。

在這之前呢,我們先看一下API沒有添加token時的結果。

然后將token的信息添加到請求頭。

// 別的模塊的請求
getCertList: function(){
      const url = '/api/cert/certManage/certList';
      // 從localStorage獲取到登錄時保持的token
      const auth = 'Token ' + localStorage.getItem('token');
      const header = {'Authorization':auth}
      axios.get(url, {'headers': header}).then(response =>{
          console.log(response.data);
          const {result, detail, errorInfo}  = response.data;
          if(result == true){
             this.certList = detail.certList;
          }else{
              this.$message({
                  showClose: true,
                  message: errorInfo,
                  type: 'error'
              });
          }
      });
}

然后在重新請求上面的API。

可以看到請求頭部已經添加上了token,而且響應的狀態碼也是200

那說明我們的登錄頁面已經成功啦。

結語

那本篇文章是不是非常簡單呢(實際的我在嘗試的過程中差點頭禿🔥),但是還是有些功能是需要優化改進的。

那下一篇文章的內容會梳理以下幾點:

1. 優化axios:請求封裝、認證信息設置的封裝 
2. 注銷  
3. 設置token過期時間  

參考文章

👉 django-rest-framework官方文檔#權限篇
👉 django-rest-framework官方文檔#授權認證篇

作者:小土豆

博客園:https://www.cnblogs.com/HouJiao/

掘金:https://juejin.im/user/58c61b4361ff4b005d9e894d

微信公眾號:不知名寶藏程序媛(關注"不知名寶藏程序媛"免費領取前端電子書籍。文章公眾號首發,關注公眾號第一時間獲取最新文章。)

碼字不易,點贊鼓勵喲~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM