Django实现JWT身份验证:原理、存储与代码示例
本文详解Django中JWT身份验证的实现机制,涵盖认证与授权的区别、JWT结构解析及存储方案对比。重点介绍将JWT存入Cookie以防范XSS攻击的方法,并提供包含登录视图与Token校验装饰器的完整Django代码示例,帮助开发者安全构建API认证系统。
1.认证与授权
1.验证:身份验证是确认个人或设备身份的过程,典型场景如登录。注册后,用户信息(ID、密码、姓名、邮箱等)存入数据库。后续访问时,只需提供用户名和密码即可通过验证,系统据此识别用户身份。
2.授权:授权是决定用户权限或访问级别的安全机制。例如在社区网站中,仅发帖者或管理员有权删除帖子。当普通用户尝试删除时,系统应返回错误(甚至隐藏删除按钮)。因此,每个请求都需验证用户是否具备相应权限。
2.什么是JWT
JSON Web令牌(JWT)是一种开放标准(RFC 7519),定义了紧凑且自包含的方式,用于在各方间安全传输JSON格式信息。JWT可用于请求的身份验证和授权。
JWT由三个Base64url编码的字符串组成:标头(Header)、有效负载(Payload)和签名(Signature),以点号分隔。标头包含令牌类型及加密算法元数据;签名用于验证令牌可信度;有效负载包含身份验证和授权所需的全部数据。
3.存储JWT
用户登录时,服务器生成JWT并发送给客户端,客户端将其存储于会话存储或本地存储。后续需认证的请求中,客户端在授权标头携带JWT。这种方式易受XSS(跨站点脚本)攻击,因为会话和本地存储可通过JavaScript访问,恶意脚本注入后可向API发起请求。
另一种方案是将JWT存储在Cookie中,服务器通过Cookie中的JWT验证用户。但Cookie随每个请求自动发送,易受CSRF(跨站请求伪造)攻击,恶意第三方可能利用此机制发起非预期请求。
4.Django中的JWT
# settings.py
SECRET_KEY = 'abcde1234',
JWT_ALGORITHM = 'HS256'
# user/views.py
import json
from datetime import datetime, timdelta
from django.conf import settings
from django.http import JsonResponse
from django.views import View
import bcrypt
import jwt
from .models import User
from token_utils import user_token
class UserSignInView(View):
def post(self, request):
try:
data = json.loads(request.body)
username = data['username']
pw_input = data['password']
user = User.objects.filter(username=username).first()
if user is None:
return JsonResponse({"message": "INVALID_USERNAME"}, status=401)
if bcrypt.checkpw(pw_input.encode('utf-8'),
user.password.encode('utf-8')):
key = settings.SECRET_KEY
algorithm = settings.JWT_ALGORITHM
token = jwt.encode(
{
'iss': 'me',
'id': user.id,
'exp': datetime.utcnow() + timedelta(days=14)
}, key, algorithm=algorithm).decode('utf-8')
response = JsonResponse(
{
'message': 'SUCCESS'
}, status=200
)
# 当使用本地/会话存储而不是Cookie时,只需在JsonResponse中发送令牌
if data.get('remember_me') is not None:
max_age = 14*24*60*60 # 14 days
expires = datetime.strftime(
datetime.utcnow() + timedelta(seconds=max_age),
"%Y-%m-%d %H:%M:%S"
)
response.set_cookie(
'token',
token,
max_age=max_age,
expires=expires,
httponly=True
)
return response
return JsonResponse({"message": "WRONG_PASSWORD"}, status=401)
except KeyError as e:
return JsonResponse({'message': f'KEY_ERROR: {e}'}, status=400)
except ValueError as e:
return JsonResponse({'message': f'VALUE_ERROR: {e}'}, status=400)
# token_utils.py
import json
from django.conf import settings
from django.http import JsonResponse
import jwt
from user.models import User
def user_token(func):
def wrapper(self, request, *args, **kwargs):
try:
token = request.COOKIES.get('token')
# token = request.headers.get('token')
key = settings.SECRET_KEY
algorithm = settings.JWT_ALGORITHM
if token is None:
return JsonResponse({"message": "INVALID_TOKEN"}, status=401)
decode = jwt.decode(token, key, algorithm=algorithm)
request.user = User.objects.get(id=decode['id'])
except jwt.ExpiredSignatureError:
return JsonResponse({"message": "EXPIRED_TOKEN"}, status=400)
return func(self, request, *args, **kwargs)
return wrapper
到此这篇关于Django中的JWT身份验证的实现的文章就介绍到这了,更多相关Django JWT身份验证内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









