自定义 JWT 中包含的信息,简直完美!

13 篇文章 0 订阅

根据 Django rest framework simple JWT 的源码分析JWT 到底是个什么串,里面包含了什么信息 的说明 和 一个来自 xdbamp 后端改造项目的灵感: 能不能自定义 JWT 中包含的信息答案是肯定的,

  1. 利用 get_token 把自定义信息加入到 token 的 payload 中
    Customizing token claims: https://github.com/davesque/django-rest-framework-simplejwt
    If you wish to customize the claims contained in web tokens which are generated by the TokenObtainPairView and TokenObtainSlidingView views,
    create a subclass for the desired view as well as a subclass for its corresponding serializer.
    Here’s an example of how to customize the claims in tokens generated by the TokenObtainPairView:

    from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
    from rest_framework_simplejwt.views import TokenObtainPairView
    class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    	@classmethod
    	def get_token(cls, user):
    		token = super().get_token(user)
    
    		# Add custom claims
    		token['name'] = user.name
    		# ...
    
    		return token
    
    class MyTokenObtainPairView(TokenObtainPairView):
    	serializer_class = MyTokenObtainPairSerializer
    

    Note that the example above will cause the customized claims to be present in both refresh and access tokens which are generated by the view.
    This follows from the fact that the get_token method above produces the refresh token for the view, which is in turn used to generate the view’s access token.
    As with the standard token views, you’ll also need to include a url route to your subclassed view.
    即:自定义一个视图类 MyTokenObtainPairView 继承 TokenObtainPairView,序列化类 MyTokenObtainPairSerializer 继承自 TokenObtainPairSerializer,然后重写 get_token 方法即可

  2. 在配置文件设置 DEFAULT_PERMISSION_CLASSES 为 rest_framework_simplejwt.authentication.JWTAuthentication 的子类
    在该子类中重写 authenticate 方法: 只需要增加 取出 JWT 中包含的自定义信息赋值给 request 的某个自定义属性像下面的语句 request.name = xxx 即可
    这样就可以在视图类的函数中任意的访问 该自定义属性了

     class MyJWTAuthentication(JWTAuthentication):
     	def authenticate(self, request):
     		header = self.get_header(request)
     		if header is None:
     			return None
    
     		raw_token = self.get_raw_token(header)
     		if raw_token is None:
     			return None
    
     		validated_token = self.get_validated_token(raw_token)
     		
     		request.name = validated_token.get('name')     --------------------------------非常重要--------------
     		
     		return self.get_user(validated_token), None
     			
     			
     
     D:\WorkSpace\Archiver\archiver_gitcode\venv\Lib\site-packages\rest_framework_simplejwt\authentication.py
     from rest_framework_simplejwt.authentication import JWTAuthentication
     class JWTAuthentication(authentication.BaseAuthentication):
     	"""
     	An authentication plugin that authenticates requests through a JSON web
     	token provided in a request header.
     	"""
     	www_authenticate_realm = 'api'
    
     	def authenticate(self, request):
     		header = self.get_header(request)
     		if header is None:
     			return None
    
     		raw_token = self.get_raw_token(header)
     		if raw_token is None:
     			return None
    
     		validated_token = self.get_validated_token(raw_token)
    
     		return self.get_user(validated_token), None
    
     	def authenticate_header(self, request):
     		return '{0} realm="{1}"'.format(
     			AUTH_HEADER_TYPES[0],
     			self.www_authenticate_realm,
     		)
    
     	def get_header(self, request):
     		"""
     		Extracts the header containing the JSON web token from the given
     		request.
     		"""
     		header = request.META.get('HTTP_AUTHORIZATION')
    
     		if isinstance(header, text_type):
     			# Work around django test client oddness
     			header = header.encode(HTTP_HEADER_ENCODING)
    
     		return header
    
     	def get_raw_token(self, header):
     		"""
     		Extracts an unvalidated JSON web token from the given "Authorization"
     		header value.
     		"""
     		parts = header.split()
    
     		if parts[0] not in AUTH_HEADER_TYPE_BYTES:
     			# Assume the header does not contain a JSON web token
     			return None
    
     		if len(parts) != 2:
     			raise AuthenticationFailed(
     				_('Authorization header must contain two space-delimited values'),
     				code='bad_authorization_header',
     			)
    
     		return parts[1]
    
     	def get_validated_token(self, raw_token):
     		"""
     		Validates an encoded JSON web token and returns a validated token
     		wrapper object.
     		"""
     		messages = []
     		for AuthToken in api_settings.AUTH_TOKEN_CLASSES:
     			try:
     				return AuthToken(raw_token)
     			except TokenError as e:
     				messages.append({'token_class': AuthToken.__name__,
     								 'token_type': AuthToken.token_type,
     								 'message': e.args[0]})
    
     		raise InvalidToken({
     			'detail': _('Given token not valid for any token type'),
     			'messages': messages,
     		})
    
     	def get_user(self, validated_token):
     		"""
     		Attempts to find and return a user using the given validated token.
     		"""
     		try:
     			user_id = validated_token[api_settings.USER_ID_CLAIM]
     		except KeyError:
     			raise InvalidToken(_('Token contained no recognizable user identification'))
    
     		try:
     			user = User.objects.get(**{api_settings.USER_ID_FIELD: user_id})
     		except User.DoesNotExist:
     			raise AuthenticationFailed(_('User not found'), code='user_not_found')
    
     		if not user.is_active:
     			raise AuthenticationFailed(_('User is inactive'), code='user_inactive')
    
     		return user
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值