本文共 4524 字,大约阅读时间需要 15 分钟。
在用户注册或登录后,我们需要记录用户的登录状态或为用户创建身份认证的凭证。与传统的Session认证机制不同,JWT(Json Web Token)采用token的方式进行认证。
JWT由三部分组成:Header(头部)、Payload(载荷)、Signature(签名)。
typ: JWT(声明类型)。alg: 加密算法(通常为HMAC SHA256)。包含以下信息:
iss(签发者)、sub(面向的用户)、aud(接收方)、exp(过期时间)、nbf(不可用时间)、iat(签发时间)、jti(唯一身份标识)。# 配置文件JWT_AUTH = { 'JWT_RESPONSE_PAYLOAD_HANDLER': 'app01.utils.new_jwt_response_payload_handler'} from rest_framework_jwt.utils import jwt_response_payload_handler, jwt_decode_handlerfrom rest_framework_jwt.authentication import BaseJSONWebTokenAuthenticationfrom rest_framework.exceptions import AuthenticationFailedimport jwtfrom app.views import modelsclass New_JWT_Authentication(BaseJSONWebTokenAuthentication): def authenticate(self, request): jwt_value = self.request.META.get('HTTP_AUTHORIZATION') if jwt_value is None: raise AuthenticationFailed('您没有携带认证信息') try: payload = jwt_decode_handler(jwt_value) except jwt.ExpiredSignature: raise AuthenticationFailed('签名过期') except jwt.DecodeError: raise AuthenticationFailed('签名解码出错') except jwt.InvalidTokenError: raise AuthenticationFailed('非法用户') except Exception as e: raise AuthenticationFailed(str(e)) user = self.authenticate_credentials(payload) return (user, jwt_value) import datetimeJWT_AUTH = { 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7)} from rest_framework import serializersfrom rest_framework.exceptions import ValidationErrorfrom rest_framework_jwt.utils import jwt_payload_handler, jwt_encode_handlerfrom app import modelsimport reclass LoginSer(serializers.ModelSerializer): username = serializers.CharField() class Meta: model = models.E_User fields = ['username', 'password'] def validate(self, attrs): username = attrs.get('username') password = attrs.get('password') if re.match('^1[3-9][0-9]{9}$', username): userobj = models.E_User.objects.filter(mobile=username).first() elif re.match('^.*@.*$', username): userobj = models.E_User.objects.filter(email=username).first() else: userobj = models.E_User.objects.filter(username=username).first() if userobj: if userobj.check_password(password): payload = jwt_payload_handler(userobj) token = jwt_encode_handler(payload) attrs['token'] = token return attrs else: raise ValidationError('密码错误') else: raise ValidationError('用户不存在') class LoginView(ViewSet): def login(self, request): login_user = app_ser.LoginSer(data=request.data) login_user.is_valid(raise_exception=True) token = login_user.data.get('token') username = login_user.data.get('username') return Response({ 'status': 100, 'msg': '登录成功', 'token': token, 'username': username }) class LoginSer1(serializers.ModelSerializer): username = serializers.CharField()class Login2View(ViewSet): def login(self, request): username = request.data.get('username') password = request.data.get('password') if re.match('^1[3-9][0-9]{9}$', username): userobj = models.E_User.objects.filter(mobile=username).first() elif re.match('^.*@.*$', username): userobj = models.E_User.objects.filter(email=username).first() else: userobj = models.E_User.objects.filter(username=username).first() if userobj: if userobj.check_password(password): payload = jwt_payload_handler(userobj) token = jwt_encode_handler(payload) loginser = LoginSer1(data=request.data) loginser.is_valid(raise_exception=True) loginser.validated_data['token'] = token loginser.validated_data.pop('password') return Response(loginser.validated_data) else: return Response('密码错误') else: return Response('用户名不存在') 转载地址:http://pfvp.baihongyu.com/