DRF的JWT用户认证
DRF的JWT用户认证
从根本上来说,JWT是一种开放的标准(RFC 7519), 全称为json web token ,其存在的意义在于,对于前后端分离的项目来说,后端不需要存储token,主需要存储签发和校验token的算法,所以我们需要在前端存储token,然后通过JWT加密之后传送给后端,从而完成校验.
JWT算法认证的最大优点在于适合服务器集群部署,这样对于比较大的项目可以从根本上提升并发量.
JWT的认证规则
JWT的格式
jwt的格式是三段式,即header(头) . payload(负载) . Signature(签名),其中头和载负载采用的是base64可逆的加密,签名采用的则是md5不可逆的加密,具体如下:
- 头(基础信息): 包含两部分,token类型以及采用的加密算法
- 载负载(核心信息): 主要是用户信息,过期时间等
- 签名(安全保证): 包括三方面,即头加密结果+载荷加密结果+服务器秘钥,采用的是md5加密
我们的后台一定要保证服务器秘钥的安全,因为在jwt里面服务器秘钥是唯一的安全保障
JWT认证的流程
后台签发token -> 前台存储 -> 前台想后台发送需要认证的请求且携带token -> 后台校验token得到合法的用户
JWT模块的导入为
# 在cmd或者Terminal窗口中:
pip install djangorestframework-jwt
# 模块包名为rest_framework_jwt
JWT的使用
JWT最常用的是三个接口,签发token,校验token以及刷新token,我们可以分别在urls.py里面导入
# /urls.py
from django.conf.urls import url
from . import views
from rest_framework_jwt.views import ObtainJSONWebToken, obtain_jwt_token, verify_jwt_token, refresh_jwt_token
urlpatterns = [
# drf-jwt三个视图接口
url(r'^login/$', obtain_jwt_token),
url(r'^verify/$', verify_jwt_token),
url(r'^refresh/$', refresh_jwt_token),
]
# 导入之后,我们还需要在settings.py里面配置相关的JWT的配置项
# /settings.py
import datetime
JWT_AUTH = {
# 设置JWT的过期时间
'JWT_EXPIRATION_DELTA':datetime.timedelta(days=7),
# 自定义jwt插件的配置
'JWT_PEFRESH_EXPIRATION_DELTA':detetime.timedelta(days=7),
# 设置JWT的头
'JWT_AUTH_HEADER_PREFIX':'JWT'
}
下面我们就用代码来实现jwt的整个逻辑,大概逻辑如下:
- 视图类中,将请求数据交给序列化完成校验,然后返回用户信息和对应token
- 序列化类,自定义反序列化的字段,利用全局钩子校验数据得到user和token,并且保存在序列化类对象中
- token可以采用jwt插件的rest_framework_jwt.serializers中jwt_payload_handler,jwt_encode_handler来完成签发
下面我们做一个实例,该小例子实现了用户的多方式登录:
# urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^login/$', views.LoginAPIView.as_view())
]
# serializers.py
from rest_framework.serializers import ModelSerializer, CharField, ValidationError, SerializerMethodField
from . import models
import re
from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
class LoginSerializer(ModelSerializer):
# 定义用户名和密码两个仅支持反序列化的字段
username = CharField(write_only=True)
password = CharField(write_only=True)
class Meta:
model = models.User
fields = ('username', 'password')
# 在全局钩子中签发token
def validate(self, attrs):
user = self._many_method_login(**attrs)
# 将数据存放到序列化对象中
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
self.user = user
self.token = token
return attrs
# 多方式登录
def _many_method_login(self, **attrs):
username = attrs.get('username')
password = attrs.get('password')
# 正则匹配,如果有@符号,则判定为邮箱登录
if re.match(r'.*@.*', username):
user = models.User.objects.filter(email=username).first()
# 如果是11位数字且开头为1,判定为手机登录
elif re.match(r'^1[0-9]{10}$', username):
user = models.User.objects.filter(mobile=username).first()
# 两个都不匹配的话,就判定为用户名登录
else:
user = models.User.objects.filter(username=username).first()
# 如果用户不存在,就是信息有误
if not user:
raise ValidationError({'username': '账号有误'})
# 如果用户存在,但是检测密码有问题,报错密码有误
if not user.check_password(password):
raise ValidationError({'password': '密码有误'})
return user
# views.py
from rest_framework.views import APIView
from . import models, serializers
from utils.response import APIResponse
class LoginAPIView(APIView):
authentication_classes = []
permission_classes = []
# 以post的方式接受前台发送的数据
def post(self, request, *args, **kwargs):
# 将前台传来的数据传送到序列化对象中,完成校验
serializer = serializers.LoginSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
return APIResponse(msg='login success', data={
'username': serializer.user.username,
'token': serializer.token
})
DRF的JWT用户认证的更多相关文章
- [django]前后端分离之JWT用户认证
在前后端分离开发时为什么需要用户认证呢?原因是由于HTTP协定是不储存状态的(stateless),这意味着当我们透过帐号密码验证一个使用者时,当下一个request请求时它就把刚刚的资料忘了.于是我 ...
- 前后端分离之JWT用户认证(转)
在前后端分离开发时为什么需要用户认证呢?原因是由于HTTP协定是不储存状态的(stateless),这意味着当我们透过帐号密码验证一个使用者时,当下一个request请求时它就把刚刚的资料忘了.于是我 ...
- 前后端分离之JWT用户认证zf
在前后端分离开发时为什么需要用户认证呢?原因是由于HTTP协定是不储存状态的(stateless),这意味着当我们透过帐号密码验证一个使用者时,当下一个request请求时它就把刚刚的资料忘了.于是我 ...
- [转] 前后端分离之JWT用户认证
[From] http://www.jianshu.com/p/180a870a308a 在前后端分离开发时为什么需要用户认证呢?原因是由于HTTP协定是不储存状态的(stateless),这意味着当 ...
- 前后端分离之JWT用户认证
在前后端分离开发时为什么需要用户认证呢?原因是由于HTTP协定是不储存状态的(stateless),这意味着当我们透过帐号密码验证一个使用者时,当下一个request请求时它就把刚刚的资料忘了.于是我 ...
- Cookie、Session、Token那点事儿和前后端分离之JWT用户认证
(两篇文章转自:https://www.jianshu.com/p/bd1be47a16c1:https://www.jianshu.com/p/180a870a308a) 什么是Cookie? Co ...
- django drf 自定义jwt用户验证逻辑
新建Backend类 from django.contrib.auth.backends import ModelBackend from django.shortcuts import render ...
- 用户认证(Authentication)进化之路:由Basic Auth到Oauth2再到jwt
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_98 用户认证是一个在web开发中亘古不变的话题,因为无论是什么系统,什么架构,什么平台,安全性是一个永远也绕不开的问题 在HTTP ...
- DRF使用JWT进行用户认证
1. 首先需要安装第三方依赖包 pip install djangorestframework-jwt 2. 在Django的settings文件中 配置全局的JWT认证类 REST_FRAMEWOR ...
随机推荐
- P1493 分梨子
P1493 分梨子 题目描述 Finley家的院子里有棵梨树,最近收获了许多梨子.于是,Finley决定挑出一些梨子,分给幼稚园的宝宝们.可是梨子大小味道都不太一样,一定要尽量挑选那些差不多的梨子分给 ...
- 3.2 Redux TodoApp
上一节讲完了 redux 中的概念,但是仍然没有和 react 联系起来,这一节将利用 redux 在 react 中实现完整的 todolist: 在 react 使用 redux 通过 Provi ...
- mysql创建新用户并且授权远程访问
1 修改root用户的密码 linux安装了mysql后,默认情况下,如果是root用户,不需要密码就可以登陆. mysql -u root -p 然后回车就可以登陆了,如果是普通用户,不能登陆. 2 ...
- 自从阿里买了Flink母公司以后,你不懂Flink就out了!
个免费报名权限 Ps:小助理手动给大家发送资料,精力有限,仅限前100名免费领取,这份资料对于想要提升大数据技能进阶的小伙伴来说,将会是一份不可或缺的宝贵资料. 特别感谢飞总的部分原创支持!
- 关于memset赋值无穷大无穷小
memset(a,,sizeof(a)); 即得到无穷大. memset(a,,sizeof(a)); 即得到无穷小,与上述的值互为相反数. memset(a,,sizeof(a)); 即近似为第一个 ...
- 2018年第九届蓝桥杯B组第四题:摔手机题解
摔手机 摔手机 动态规划 在蓝桥杯的时候遇到一次 当时没有做对 看了题解也没明白 如今再次遇到这个类似的题目 于是拿出来补补吧 摔手机题目如下: 星球的居民脾气不太好,但好在他们生气的时候唯一的 ...
- .Net中Task使用来提高代码执行效率
技术不断更新迭代,更高效的执行效率越来越被重视,所以对Task的使用进行了简单使用做了整理与大家分享. .Net 中有了Task后使多线程编程更简单使用和操作,下面粘上代码进行简单说明: /// &l ...
- PHP72w安装
PHP72w # rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm # rpm ...
- 基本TCP Sockets编程
一.socket 函数 #include <sys/socket.h> int socket (int family, int type, int protocol); Returns: ...
- 谷歌浏览器控制台出现 Unchecked runtime.lastError: The message port closed before a response was received. 的报错
错误截图: 解决:经过网上搜索说是浏览器扩展程序的问题,把那个扩展程序删除或者禁用就可以了