一、概念
Authentication即验证,Permissions即权限。
Authentication验证是将传入请求与一组标识凭据(例如请求来自的用户或用于签名的令牌)相关联的机制。然后,Permissions权限决定了是否应该授予或拒绝访问请求。
这里一定要注意,只配置了Authentication,接口依然是可以访问的。决定接口是否能够访问需要与Permissions一起配置。
二、Authentication
1、设置验证方案的3种方式:
(1)在settings中设置全局默认身份验证方案DEFAULT_AUTHENTICATION_CLASSES:
(2)使用装饰器,在基于函数的视图上设置身份验证方案:
(3)使用APIView基于类的视图在每个视图或每个视图集的基础上设置身份验证方案:
2、身份认证类
(1)基本认证:BasicAuthentication
(2)会话认证:SessionAuthentication
(3)令牌认证:TokenAuthentication
首先,在APP中增加rest_framework.authtoken,如图:
第二,执行命令python manage.py migrate同步数据库表,auth_user表是django框架生成的用户表,接下来就使用这个表来保存用户的信息;authtoken_token表是和用户登录认证相关的数据表,用来存放用户token。
第三,我们创建一个用户,用于后期的登录测试,执行命令:python manage.py createsuperuser,创建成功后auth_user表就有了刚刚创建的数据。
接下来,我们来实现这个登录接口,编写views.py:
配置urls.py:
大家自行用接口测试工具提交post请求到登录接口,我这边就使用了DRF自带的界面操作:
因为是首次登录,所以会为该用户创建token,即authtoken_token会产生一条记录:
到这里就完成了登录认证,大家可以用接口测试工具测试,如果请求头中不包含该token,那么无法获取到数据:
如果请求头中包含token,以字符串文字“Token”为前缀,用空格分隔两个字符串。例如:请求头的格式:"Authorization":"Token XXXXXXXXXXXXXXXXXXXXXXXX"
(4)第三方包DRF-JWT
JWT:json web tokens,采用json格式在web上传输的认证字符串。
DRF中对应的JWT包为:django-rest-framework-jwt,安装pip install djangorestframework-jwt,增加认证配置:
在项目的urls.py中配置:
编写views.py:
测试一下,成功:
前端的其他请求,需要在请求头中加入token,格式如下:"Authorization":"JWT <token>",如果希望token的前缀不要是JWT,例如是Bearer,可在settings中配置JWT_AUTH,如:
注意:由于drf-jwt的登录验证默认只支持使用username。
三、Permissions
权限决定了是否应该授予或拒绝访问请求。
权限检查总是在视图的最开始运行,在任何其他代码被允许继续之前。
权限检查通常使用request.user和request.auth属性中的身份验证信息来确定是否应允许传入请求。
1、设置权限方案的3种方式
与Authentication设置一致。
2、权限类型
IsAuthenticated:最简单的权限样式,允许任何经过身份验证的用户访问,并拒绝任何未经身份验证的用户访问。
IsAuthenticatedOrReadOnly:一种稍微不那么严格的权限样式,允许对经过身份验证的用户进行完全访问,但允许对未经身份验证的用户进行只读访问。
AllowAny:允许无限制访问。
IsAdminUser:只允许管理员用户访问。
3、自定义权限
要实现自定义权限,需要覆盖BasePermission,并实现以下任一方法或两者:
(1).has_permission(self, request, view)
(2).has_object_permission(self, request, view, obj)
(3)True表示条件通过,False表示条件不通过。
四、自定义认证与自定义权限的使用
由于drf-jwt是基于django自带的认证系统(库中的auth_user表)来实现的,我自己的库的Users表是没有username字段的,且登录验证使用字段user_no和password,所以使用pyjwt实现了令牌认证,如图,根据user_no与password生成token:
views.py中登录的token生成使用get_jwt_token方法:
生成了token之后,怎么样才能让其他接口都走这个JWT的验证机制呢?
1、自定义认证
参照官方文档:要实现自定义身份验证方案,需继承BaseAuthentication类,并使用authenticate(self, request)方法,返回user, auth。如图,新建一个myauth.py文件,这里写的比较简单,还可以加上验证token是否过期等:
配置自定义认证,我这里使用的是全局配置的方式,在settings中配置:
2、自定义权限
用户认证完成后,需要配置权限,权限决定了请求是否能够通过,要求任何经过身份验证的用户都访问,但是拒绝任何未经身份验证的用户访问。由于Users表是使用我自己创建的表,使用默认的权限('rest_framework.permissions.IsAuthenticated')会报错:not request.user.is_authenticated,所以使用自定义的权限。
新建一个myperm.py文件,写的比较简单:
配置自定义权限,我这里也是使用的是全局配置的方式,在settings中配置:
以上,就完成了一个项目最基础的验证和权限。
可以使用接口测试工具测试一下,先POST登录接口,获取JWT,在使用该用户的JWT访问其他接口,就可以获取到数据。
如果请求头中没有携带JWT或者JWT错误,是无法获取到数据的。