微信小程序-drf登录认证组件
- 通过全局的用户判断是否登录
- 登录用户则校验用户的token值
1. config - settings.js
- api.js
- settings.js
# 模块化:登录页面路由
module.exports = {
loginPage: "/pages/login/login"
}
2. utils - auth.js
- auth.js
# 获取应用实例
var settings = require('../config/settings.js')
var app = getApp()
function authentication() {
if (!app.globalData.userInfo) {
wx.navigateTo({
// settings.loginPage,登录路由
url: settings.loginPage
})
return false
}
return true
}
# 认证函数模块化
module.exports = {
authentication: authentication
}
3. 示例:用户评论
pages
- newsDetail
- newsDetail.js
// pages/newsDetail/newsDetail.js
var api = require("../../config/api.js")
var auth = require('../../utils/auth.js')
var app = getApp()
# 评论之前判断用户是否登录
onClickShowCommentModal: function(e) {
if (!auth.authentication()) {
return
}
var replyInfo = e.currentTarget.dataset;
this.setData({
isShowCommentModal: true,
reply: replyInfo,
});
},
4. 提交评论-- 用户已登录,发送请求携带token值
'''
# 请求头携带用户的token值,此处涉及到js的三元运算
header: {
Authorization: userInfo ? "token " + userInfo.token : ""
},
'''
onClickPostComment: function() {
// 发布评论,将评论数据发送到后台接口
var userInfo = app.globalData.userInfo;
wx.request({
url: api.Comment,
data: this.data.reply,
method: 'POST',
dataType: 'json',
header: {
Authorization: userInfo ? "token " + userInfo.token : ""
},
responseType: 'text',
success: (res) => {
...
}
})
}
5. 后端校验 token值是否一致
utils
- auth.py
'''
如果用户已登录,则在request.user和request.auth中赋值;未登录则做任何操作。
用户需要在请求头Authorization中传递token,格式如下:
Authorization: token 401f7ac837da42b97f613d789819ff93537bee6a
建议:配合和配置文件一起使用,未认证的用户request.user和request.auth的值为None
REST_FRAMEWORK = {
"UNAUTHENTICATED_USER":None,
"UNAUTHENTICATED_TOKEN":None
}
'''
通用认证
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.authentication import BaseAuthentication
from rest_framework.authentication import get_authorization_header
from apps.api import models
from rest_framework import exceptions
class GeneralAuthentication(BaseAuthentication):
"""
通用认证(所有页面都可以应用)
"""
keyword = "token"
def authenticate(self, request):
# 认证元组
auth_tuple = get_authorization_header(request).split()
# 1.如果没有传token,则通过本次认证,进行之后的认证
if not auth_tuple:
return None
# 2.如果传递token,格式不符,则通过本次认证,进行之后的认证
if len(auth_tuple) != 2:
return None
# 3.如果传递了token,但token的名称不符,则通过本次认证,进行之后的认证
if auth_tuple[0].lower() != self.keyword.lower().encode():
return None
# 4.对token进行认证,如果通过了则给request.user和request.auth赋值,否则返回None
try:
token = auth_tuple[1].decode()
user_object = models.UserInfo.objects.get(token=token)
return (user_object, token)
except Exception as e:
return None
用户认证
class UserAuthentication(BaseAuthentication):
"""
token 认证
"""
keyword = "token"
def authenticate(self, request):
auth_tuple = get_authorization_header(request).split()
'''
print(auth_tuple)
auth_tuple = [b'token', b'a33409078e8ff69c16e813442ac1ce5d']
'''
if not auth_tuple:
raise exceptions.AuthenticationFailed('认证失败')
if len(auth_tuple) != 2:
raise exceptions.AuthenticationFailed('认证失败')
if auth_tuple[0].lower() != self.keyword.lower().encode():
raise exceptions.AuthenticationFailed('认证失败')
try:
token = auth_tuple[1].decode()
user_object = models.UserInfo.objects.get(token=token)
return (user_object, token)
except Exception as e:
raise exceptions.AuthenticationFailed('认证失败')
视图函数添加认证类 --评论
from utils.auth import UserAuthentication, GeneralAuthentication
class CommentView(CreateAPIView, ListAPIView):
'''
POST请求提交评论:用户认证类
'''
serializer_class = CommentModelSerializer
queryset = models.CommentRecord.objects
filter_backends = [ChildCommentFilter, ]
def get_authenticators(self):
if self.request.method == 'POST':
return [UserAuthentication(), ]
return [GeneralAuthentication(), ]
|
请发表评论