认证可以简单的理解为登录和访问需要登录的接口的认证。只要认证通过了,那么在request对象(是drf的request对象)上便有两个属性,一个是request.user,一个是request.auth,前者就是django中的User对象,后者根据不同的认证机制有不同的对象。DRF内置了几个认证的模块。以下进行简单了解。
基本的授权。每次都要在Header中把用户名和密码传给服务器,因此不是很安全,不能在生产环境中使用。
基于django的session机制实现的。如果前端部分是网页,那么用他是可以的,如果前端是iOS或者Android的app,用他就不太方便了(如果要用也是完全可以的)。
基于token的认证机制。只要登录完成后便会返回一个token,以后请求一些需要登录的api,就通过传递这个token就可以了,并且这个token是存储在服务器的数据库中的。
但是这种token的方式有一个缺点,就是他没有自动过期机制,一旦登录完成后,这个token是永久有效的,这是不安全的。
JSON Web Token简称JWT。在前后端分离的项目中,或者是app项目中,推荐使用JWT。JWT是在登录成功后,把用户的相关信息(比如用户id)以及过期时间进行加密,然后生成一个token返回给客户端,客户端拿到后可以存储起来,以后每次请求的时候都携带这个token,服务器在接收到需要登录的API请求后,对这个token进行解密,然后获取过期时间和用户信息(比如用户id),如果过期了或者用户信息不对,那么都是认证失败。JWT的相关代码如下:
import jwt
from django.conf import settings
from rest_framework.authentication import BaseAuthentication,get_authorization_header
from rest_framework import exceptions
from django.contrib.auth import get_user_model
from jwt.exceptions import ExpiredSignatureError
MTUser = get_user_model()
import time
def generate_jwt(user):
expire_time = int(time.time() + 60*60*24*7)
return jwt.encode({"userid":user.pk,"exp":expire_time},key=settings.SECRET_KEY)
class JWTAuthentication(BaseAuthentication):
"""
Authorization: JWT 401f7ac837da42b97f613d789819ff93537bee6a
"""
keyword = 'JWT'
model = None
def authenticate(self, request):
auth = get_authorization_header(request).split()
if not auth or auth[0].lower() != self.keyword.lower().encode():
return None
if len(auth) == 1:
msg = 'Authorization不可用!'
raise exceptions.AuthenticationFailed(msg)
elif len(auth) > 2:
msg = 'Authorization不可用!应该提供一个空格!'
raise exceptions.AuthenticationFailed(msg)
try:
jwt_token = auth[1]
jwt_info = jwt.decode(jwt_token, settings.SECRET_KEY, algorithms="HS256")
userid = jwt_info.get('userid')
try:
user = User.objects.get(pk=userid)
return (user, jwt_token)
except Exception:
msg = '用户不存在!'
raise exceptions.AuthenticationFailed(msg)
except UnicodeError:
msg = 'token格式错误!'
raise exceptions.AuthenticationFailed(msg)
except jwt.ExpiredSignatureError:
msg = 'token已过期!'
raise exceptions.AuthenticationFailed(msg)
配置认证有两种方式,一种是全局的,在settings.REST_FRAMEWORK.DEFAULT_AUTHENTICATION_CLASSES中配置。第二种就是在需要认证的视图中,通过authentication_classes进行配置。示例代码如下:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ['apps.mtauth.authentications.JWTAuthentication'],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 12,
'PAGE_QUERY_PARAM': "page"
}
不同的API拥有不同的访问权限。比如普通用户有读文章的权限,但是没有删除文章的权限。因此需要用到权限来进行API的管理。以下是DRF自带的权限。
允许所有人访问。