关于JWT(Json Web Token)是一种较新的用户认证方式,官网在 这里 ,网上有篇中文解释写的很好, 点此跳转 。
用户认证(Authentication)和用户授权(Authorization)是两个不同的概念,认证解决的是“有没有”的问题,而授权解决的是“能不能”的问题。
一般用到JWT认证的情况大多都是配合REST框架使用,比如我大Django的Django-REST-framework框架,就已经有了现成的三方库 django-rest-framework-jwt
。不过这个库默认只支持基于 Header
传递信息,所以改成基于Cookie方式还需要我们来手动处理一下。
关于安装,直接使用pip安装即可,在 settings.py
中,先来修改django-restframework的基本配置如下:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'app.myauth.CookieAuthentication',
),
'PAGE_SIZE': 20,
}
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300), # 过期时间
'JWT_AUTH_HEADER_PREFIX': 'ABC', # 请求头前缀
}
至于 JWT_AUTH
更多的配置见官网,比如使用什么加密算法等等。
接下来编写认证代码,这里逻辑很简单, app/myauth.py
内容如下:
# coding=utf-8
from rest_framework_jwt.settings import api_settings
from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication
classCookieAuthentication(BaseJSONWebTokenAuthentication):
"""自定义JWT认证,从cookie中获取认证信息"""
defget_jwt_value(self, request):
# print request.COOKIES
return request.COOKIES.get(api_settings.JWT_AUTH_HEADER_PREFIX.upper(), '')
然后编写我们自己的获取JWT-Token的View,编辑 app/views.py
添加如下代码:
from datetime import datetime
from rest_framework import status
from rest_framework.response import Response
from rest_framework_jwt.settings import api_settings
from rest_framework_jwt.views import ObtainJSONWebToken
classCookieJSONWebToken(ObtainJSONWebToken):
"""
接受post请求生成JWT-Token并设置cookie
"""
defpost(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
user = serializer.object.get('user') or request.user
token = serializer.object.get('token')
response_data = api_settings.JWT_RESPONSE_PAYLOAD_HANDLER(
token, user, request)
res = Response(response_data)
res.set_cookie(api_settings.JWT_AUTH_HEADER_PREFIX.upper(), value=response_data[
'token'], httponly=True, expires=datetime.now() + api_settings.JWT_EXPIRATION_DELTA)
return res
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
这里注意设定httponly属性,防止造成安全漏洞。
最后,修改 urls.py
添加我们的view:
from app import views as baseview
urlpatterns = [
...
url(r'^api-token-auth/', baseview.CookieJSONWebToken.as_view()),
...
]
设定完成后,就可以通过向 api-token-auth
这个URL提交用户名密码来获取JWT-Token了,并且在浏览器使用ajax请求获取那些登录后的数据会自动带上cookie进行认证。至于如何解决跨域,可以使用 django-cors-headers
。