全文1546字,可能需要您5分钟.
共三部分:
一.JWT的概念
二.django restfulframework_jwt源码分析
三.基于django中间件实现跳转页面的鉴权工作
因为采用前后端分离的技术,所以考虑使用JWT来进行页面授权,这个问题想了好久,有点难懂,主要是跳转页面的鉴权问题.
一.JWT的概念
json web token是用来代替cookie-session鉴权方案,用在前后端分离的项目中,来进行鉴权的一套解决方案.
二.django restfulframework_jwt源码分析
一些概念上的东西网上都有,下面我们看一下djangorestfulframework-jwt的相关源码.
JWT由三部分组成,分别是payload,header,signature.payload为用户的一些非私密信息(一般是user_id,username,email,expire_time)进过base64url编码之后的结果.header为加密算法,signature是前两者加入秘钥之后加密而成.
def jwt_get_secret_key(payload=None):"""For enhanced security you may want to use a secret key based on user.This way you have an option to logout only this user if:- token is compromised- password is changed- etc."""if api_settings.JWT_GET_USER_SECRET_KEY:User = get_user_model() # noqa: N806user = User.objects.get(pk=payload.get('user_id'))key = str(api_settings.JWT_GET_USER_SECRET_KEY(user))return keyreturn api_settings.JWT_SECRET_KEY
jwt_get_secret_key方法用来得到秘钥,可以看见
'JWT_SECRET_KEY': settings.SECRET_KEY,
默认的秘钥是django自动生成的SECRET_KEY,可以通过自定义,在设置中添加
'JWT_GET_USER_SECRET_KEY': 'chat_app.fresh_jwt.get_jwt_secret_key',# 基于用户信息发送签名
在/chat_app/fresh_jwt.py中通过实现get_jwt_secret_key函数来动态更新秘钥,基于用户个人信息的秘钥,更加安全.
def jwt_payload_handler(user):username_field = get_username_field()username = get_username(user)warnings.warn('The following fields will be removed in the future: ''`email` and `user_id`. ',DeprecationWarning)payload = {'user_id': user.pk,'username': username,'exp': datetime.utcnow() + api_settings.JWT_EXPIRATION_DELTA}if hasattr(user, 'email'):payload['email'] = user.emailif isinstance(user.pk, uuid.UUID):payload['user_id'] = str(user.pk)payload[username_field] = username# Include original issued at time for a brand new token,# to allow token refreshif api_settings.JWT_ALLOW_REFRESH:payload['orig_iat'] = timegm(datetime.utcnow().utctimetuple())if api_settings.JWT_AUDIENCE is not None:payload['aud'] = api_settings.JWT_AUDIENCEif api_settings.JWT_ISSUER is not None:payload['iss'] = api_settings.JWT_ISSUERreturn payload
jwt_payload_handler函数用来生成payload.
def jwt_encode_handler(payload):key = api_settings.JWT_PRIVATE_KEY or jwt_get_secret_key(payload)return jwt.encode(payload,key,api_settings.JWT_ALGORITHM).decode('utf-8')
jwt_encode_handler函数用来对payload,秘钥,加密算法信息进行加密.
def jwt_decode_handler(token)函数用来对token进行decode,返回payload中的内容.
三.基于django中间件实现跳转页面的鉴权工作
主要的思路如下:
用户分为两种:未鉴权用户和已鉴权用户,未鉴权用户只能进入注册和登录页面.
在这两个页面中的任何request不需要添加authorization请求头,进入其他页面必须使用authorization进行鉴权.
在注册页面中用户提交个人信息成功后,调用/token/,post username和password,请求得到authorization.在进入其他页面之前,调用**valid_token/**判断该authorization是否有效,有效则允许跳转.
在登录页面中,直接,调用/token/,post username和password,请求得到authorization.在进入其他页面之前,调用**valid_token/**判断该authorization是否有效,有效则允许跳转.
由于可以使用同一username和password获得多个有效token,则有可能同时使用同一身份同时操作,为此利用中间件进行拦截:
编写django中间件
class ValidJwt(MiddlewareMixin):def process_request(self, request):# 保证设备登录的唯一性jwt_token = request.META.get('HTTP_AUTHORIZATION', None)if jwt_token is not None and jwt_token != "":data = {'token': jwt_token}try:valid_data = VerifyJSONWebTokenSerializer().validate(data)user = valid_data['user']except (InvalidSignatureError, ValidationError):# 找不到用户res = {"msg": "token invalid","code": "-1"}return HttpResponse(json.dumps(res), content_type='application/json', status=400)if user.jwt_token != data['token']:res = {"msg": "token error","code": "-2"}user.jwt_key = uuid.uuid4()user.save()return HttpResponse(json.dumps(res), content_type='application/json', status=400)else:print("pass")
对于所有带有authorization请求头的request,均需要判断它的有效性,token失效返回-1,如果token与该用户的model中存储的token不一致,返回-2,同时更新在model中存储的key秘钥,使用uuid.uuid4制造随机数,保存,直接结束请求.
class Jwt_Response(MiddlewareMixin):def process_response(self, request, response):if request.method != 'POST':return responseelse:if request.META['PATH_INFO'] == '/token/': # 当请求获得token时rep_data = response.dataif "token" in rep_data: #账号与密码有效valid_data = VerifyJSONWebTokenSerializer().validate(rep_data)user = valid_data['user']user.jwt_token = rep_data['token']user.save()return responseelse:print("没有响应token")return response
在响应返回时对/token/的请求响应进行判断:
如果token正在返回一个新的token给用户,此时需要更新数据库中的user.jwt_token,以保证始终只有一个用户能够登录成功.
更多优质内容,请关注微信公众号:生物信息与python
如果觉得《django登录跳转到另一个页面_[JWT]djangojson web token实现单用户登录》对你有帮助,请点赞、收藏,并留下你的观点哦!