jwt
这里主要分享的是drf的jwt。原因如下:
Json web token,是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,
特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器
获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
安装配置与登录
安装
pip install djangorestframework-jwt==1.11.0
配置
# jwt载荷中的有效期设置
JWT_AUTH = {
# 1.token前缀:headers中 Authorization 值的前缀
'JWT_AUTH_HEADER_PREFIX': 'JWT',
# 2.token有效期:3天
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=3),
'JWT_ALLOW_REFRESH': False,
# 4.token有效期:token在24小时内过期, 可续期token
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(hours=24),
# 5.自定义JWT载荷信息:自定义返回格式,需要手工创建;jwt_response_payload_handler这个方法名字是严格一致的,本质就是覆盖
'JWT_RESPONSE_PAYLOAD_HANDLER': 'user.utils.jwt_response_payload_handler',
}
自定义返回格式
def jwt_response_payload_handler(token, user=None, request=None):
return {
"d": status.HTTP_200_OK,
'token': 'jwt ' + token,
}
开发者有提取token信息的必要可以看
def parser_header(header):
if header:
import base64
split_num = 4
remainder = len(header.split('.')[1]) % split_num
if remainder:
supply_num = "=" * (split_num - remainder)
auth = header.split('.')[1] + supply_num
else:
auth = header.split('.')[1]
ret = base64.b64decode(auth)
return json.loads(ret)
else:
return {}
parser_header(request.META.get('HTTP_AUTHORIZATION', b''))
登录
from rest_framework.authtoken.views import obtain_auth_token
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
path('login/', obtain_jwt_token), # 获取token,登录视图
]
测试
测试工具:
postman或apipost测试都没问题
注意:
必须使用post请求,的确存在某些场景会使用get来登录但是obtain_jwt_token不支持get请求
权限
全局配置
# 在DRF配置文件中开启认证和权限
REST_FRAMEWORK = {
# 用户登陆认证方式
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_jwt.authentication.JSONWebTokenAuthentication', # 在DRF中配置JWT认证
# 'rest_framework.authentication.SessionAuthentication', # 使用session时的认证器
# 'rest_framework.authentication.BasicAuthentication' # 提交表单时的认证器
],
# 权限配置【一般不在这里配置,因为这里是全局生效的,局限性较大】
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAdminUser', # 管理员可以访问
'rest_framework.permissions.IsAuthenticated', # 全局配置只有认证用户可以访问接口
'rest_framework.permissions.IsAuthenticatedOrReadOnly', # 认证用户可以访问, 否则只能读取
'rest_framework.permissions.AllowAny', # 所有用户都可以访问
],
}
局部配置【要求前端传递的token是管理员身份】
from rest_framework.permissions import IsAuthenticated,IsAdminUser
class UserRestPasswordAPIView(ListAPIView, APIView):
permission_classes = [IsAuthenticated, IsAdminUser]
def get(self, request, *args, **kwargs):
password = "随机数,开发者自行实现"
user = User.objects.get(pk=user_id)
if not user:
return Response({"d": status.HTTP_400_BAD_REQUEST})
user.set_password(password)
user.save()
return Response({"d": "ok", "new_password": password})
多位随机数生成
ALLOWED_CHARS = [
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z',
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'
]
def random_string_generator(str_size):
return ''.join(random.choice(ALLOWED_CHARS) for i in range(str_size))
user并不在默认的数据库如何重置密码
def get(self, request, *args, **kwargs):
password = "随机数,开发者自行实现"
user = User.objects.using("db").get(pk=user_id)
if not user:
return Response({"d": status.HTTP_400_BAD_REQUEST})
user.set_password(password)
user.save()
return Response({"d": "ok", "new_password": password})
user并不在默认的数据库如何添加用户
这里就不能直接调用using().get的方式,需要使用管理器实现
User.objects.db_manager('db').create_user()
多库问题的总结
其本质可以归纳为,使用user=User.objects.using("db").get(pk=user_id)的get去查找参数,根据其返回的对象,而不是一个查询。
可以使用user.save();user.delete();等操作
注意
使用drf自带的权限,那么用户表必须继承自django内置的用户表以及权限。否者重视可以登录,权限的限制也是使用不了。一直会发生invalid token
参考链接
https://www.cnblogs.com/fiee/p/13771806.html
https://www.cnblogs.com/ltyc/category/1907572.html
标签:get,jwt,JWT,rest,token,user,drf From: https://www.cnblogs.com/topass123/p/16609621.html