美多后臺準備
-
后臺倉庫的創(chuàng)建
- gitee上新建倉庫meiduo_admin
- 給meiduo_admin添加dev分支
- 復制倉庫的SSH
- 在本地終端中對gitee上新建的倉庫進行克隆
git clone SSH
- 在項目目錄下,將dev分支克隆到本地
git checkout -b dev origin/dev
- 在本地創(chuàng)建項目分支并切換到項目分支
git checkout -b 項目分支名
- 將后臺項目文件夾復制到項目目錄下旋讹,再將項目文件推送到gitee
git add ./ git cimmit -m '說明信息' git push
-
前端運行
- 在前端項目文件下殖蚕,執(zhí)行
npm run dev
,開啟前端服務,前端為8080端口 或者在vs code 中打開項目沉迹,運行npm run dev
- 在瀏覽器進行前端訪問
- 在前端項目文件下殖蚕,執(zhí)行
-
后端運行
- 在Pycharm中打開后臺項目并配置Django虛擬環(huán)境
- 在version control中添加git
ctrl + k:commit ctrl + shift + k:push
- 在終端中導入項目數(shù)據(jù)庫
mysql -uroot -p < *.sql
- 在pycharm中連接數(shù)據(jù)庫
- pycharm中運行后臺項目睦疫,后臺端口為8000
- 編輯運行,runserver
- 開啟redis服務
- 在瀏覽器進行后端訪問
美多后臺登錄
- 后臺項目架構
-開發(fā)模式:前后端分離- 前端框架:VUE
- 后端框架:Django REST framework
- 功能部分:管理員登陸鞭呕,數(shù)據(jù)統(tǒng)計蛤育,用戶管理,商品管理葫松,訂單管理瓦糕,權限管理
- 主要技術:JWT用戶認證,CORS跨域
- 項目搭建:在原有項目基礎上創(chuàng)建一個meiduo_admin的子應用腋么,在子應用中完成后臺的所有功能
-
python manage.py startapp meiduo_admin
,注意manage.py所在的相對路徑, 將apps右擊指定為導包路徑 - 將子應用和rest_framework注冊到配置文件中
-
- 登錄
在后臺登錄時咕娄,前端與后端服務的域名不同,需要先解決跨域問題珊擂,登錄后的狀態(tài)保持采用jwt- 跨域CORS
-前端與后端分處不同的域名圣勒,涉及到跨域訪問數(shù)據(jù)的問題费变,因為瀏覽器的同源策略,默認不支持兩個不同域間相互訪問數(shù)據(jù)圣贸,如果需要在兩個域名間相互傳遞數(shù)據(jù)挚歧,就要為后端添加跨域訪問的支持- 只用CORS解決后端對跨域訪問的支持,使用django-cors-headers擴展
- 安裝
pip install django-cors-headers
-添加應用吁峻,在配置文件中注冊'corsheaders' - 中間層設置昼激,添加在第一位,'corsheaders.middleware.CorsMiddleware'
- 添加白名單
#添加白名單 # CORS CORS_ORIGIN_WHITELIST = ( 'http://127.0.0.1:8080', 'http://localhost:8080', 'http://www.meiduo.site:8080', 'http://127.0.0.1:8000' ) CORS_ALLOW_CREDENTIALS = True # 允許攜帶cookie
- JWT
在用戶注冊或登錄后锡搜,為了記錄用戶的登錄狀態(tài)橙困,創(chuàng)建用戶身份認證的憑證。這里不再使用Session認證機制耕餐,而使用Json Web Token認證機制
瀏覽器在訪問后端時凡傅,先發(fā)送options詢問請求,進行跨域驗證肠缔,后端允許訪問并返回200夏跷,瀏覽器再發(fā)送post請求,與后端進行數(shù)據(jù)訪問
-
session認證的三個缺點
- session存儲在Redis中明未,隨著認證用戶的增多槽华,服務器開銷增大
- 擴展性問題:用戶認證記錄被保存在一臺服務器內(nèi)存中,再次訪問趟妥,必須請求這臺服務器猫态,才能被授權,用戶狀態(tài)保持可能會失效披摄,限制了負載均衡
- CSRF:瀏覽器只要發(fā)送請求亲雪,就會攜帶cookie,基于cookie用來用戶識別疚膊,一旦被截獲义辕,用戶很容易受到跨站請求偽造的攻擊
-
基于token的認證機制目派,針對session認證的三個缺點
- token存儲在瀏覽器的storage中弄痹,對后端服務器開銷無影響
- 擴展性:解密token的的代碼相同醉拓,不影響服務器擴展
- 安全:同域名的前端js代碼才能提取token
-
JWT構成孔厉,三部分信息構成顽照,三段信息文本由.連接構成JWT字符串
-
第一部分為頭部(header)蹦漠,含聲明類型(jwt)和加密算法(sha256)
{ 'typ': 'JWT', 'alg': 'HS256' } 再對頭部進行base64加密挑随,構成第一部分
-
第二部分為載荷(payload),存放有效信息扛点,有效信息包含三部分
-
標準中注冊的聲明
iss: jwt簽發(fā)者 sub: jwt所面向的用戶 aud: 接收jwt的一方 exp: jwt的過期時間喳张,這個過期時間必須要大于簽發(fā)時間 nbf: 定義在什么時間之前续镇,該jwt都是不可用的. iat: jwt的簽發(fā)時間 jti: jwt的唯一身份標識,主要用來作為一次性token,從而回避 重放攻擊销部。
公共的聲明:公共的聲明可以添加任何的信息摸航,一般添加用戶的相關信息或其他業(yè)務需要的必要信息.但不建議添加敏感信息制跟,因為該部分在客戶端可解密
私有的聲明:私有聲明是提供者和消費者所共同定義的聲明,一般不建議存放敏感信息酱虎,因為base64是對稱解密的雨膨,意味著該部分信息可以歸類為明文信息
{ "sub": "1234567890", "name": "John Doe", "admin": true } 再對其進行base64加密,構成第二部分
-
-
第三部分為簽證(signature),這個部分需要base64加密后的header和base64加密后的payload使用.連接組成的字符串读串,然后通過header中聲明的加密方式進行加鹽secret組合加密聊记,然后就構成了jwt的第三部分
-secret是保存在服務器端的,jwt的簽發(fā)生成也是在服務器端的恢暖,secret就是用來進行jwt的簽發(fā)和jwt的驗證排监,所以,它就是你服務端的私鑰杰捂,在任何場景都不應該流露出去舆床。一旦客戶端得知這個secret, 那就意味著客戶端是可以自我簽發(fā)jwt了- header (base64后的)
- payload (base64后的)
- secret
-
服務器驗證token的流程
-
-
總結(jié)
- 因為json通用,JWT是可以進行跨語言支持的嫁佳,像JAVA,JavaScript,NodeJS,PHP等很多語言都可以使用
- 有了payload部分挨队,JWT可以在自身存儲一些其他業(yè)務邏輯所必要的非敏感信息
- 便于傳輸,jwt的構成非常簡單蒿往,字節(jié)占用很小盛垦,非常便于傳輸?shù)?/li>
- 不需要在服務端保存會話信息, 所以它易于應用的擴展
- 安全相關
- 不應該在jwt的payload部分存放敏感信息,因為該部分是客戶端可解密的部分
- 保護好secret私鑰瓤漏,該私鑰非常重要
- 如果可以腾夯,請使用https協(xié)議
-
JWT使用
- 安裝配置
pip install djangorestframework-jwt REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication', ), } JWT_AUTH = { 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1), } #指明token的有效期
- 賬號登錄
業(yè)務說明:驗證用戶名和密碼,驗證成功后赌蔑,為用戶簽發(fā)JWT俯在,前端將簽發(fā)的JWT保存下來
-
后端接口設計
- 請求方式和路徑:POST meiduo_admin/authorizations/
- 請求參數(shù):JSON或表單(username和pwd)
- 返回數(shù)據(jù):JSON(username,id和token)
-
后端實現(xiàn)娃惯,重寫jwt_response_payload_handler方法,因為默認的返回值只有token
#總路由配置 url('^meiduo_admin/', include('meiduo_admin.urls')), #子路由配置 url(r'^authorizations/$', obtain_jwt_token) #重寫jwt_response_payload_handler方法 def jwt_response_payload_handler(token, user=None, request=None): #自定義jwt認證成功返回數(shù)據(jù) return { 'id': user.id, 'username': user.username, 'token': token } #配置重寫的方法 JWT_AUTH = { 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1), 'JWT_RESPONSE_PAYLOAD_HANDLER': 'meiduo_admin.utils.jwt_response_payload_handler', } #對于管理員用戶和普通用戶登錄進行路徑判斷 from django.contrib.auth.backends import ModelBackend from django.http import HttpRequest import re from users.models import User class MeiduoModelBackend(ModelBackend): def authenticate(self, request, username=None, password=None, **kwargs): if request is None: #JWT中未返回request肥败,用來判斷是管理員用戶 try: user = User.objects.get(username=username, is_staff=True) except: return None # 判斷密碼 if user.check_password(password): return user else: # 變量username的值趾浅,可以是用戶名,也可以是手機號馒稍,需要判斷皿哨,再查詢 try: user = User.objects.get(username=username) except: # 如果未查到數(shù)據(jù),則返回None纽谒,用于后續(xù)判斷 try: user = User.objects.get(mobile=username) except: return None # return None # 判斷密碼 if user.check_password(password): return user else: return None
前端保存token证膨,瀏覽器的本地提供sessionStorage(瀏覽器關閉即失效)和 localStorage(長期有效) 兩種
- 安裝配置
- 跨域CORS