1、优化后的登陆接口
- 利用pickle模块可以直接读写对象的特性,将从数据库中查到的用户对象直接存入Redis中 ```python import hashlib import json import pickle import time
import django_redis from django.forms import model_to_dict from django.http import JsonResponse from django.db.models import Q from django.shortcuts import render from . import models
Create your views here.
注册接口
def register(request): email = request.POST.get(“email”) nick = request.POST.get(“nick”) phone = request.POST.get(“phone”) password = request.POST.get(“password”) password2 = request.POST.get(“password2”)
if email and nick and phone and password:
if password != password2:
return JsonResponse({"code": -1, "msg": "两次输入的密码不一致"})
user_email = models.NewUser.objects.filter(email=email)
user_phone = models.NewUser.objects.filter(phone=phone)
if user_email.exists():
return JsonResponse({"code": -1, "msg": "email exists"})
if user_phone.exists():
return JsonResponse({"code": -1, "msg": "phone exists"})
new_password = md5(password)
user = models.NewUser(email=email, nick=nick, phone=phone, password=new_password)
user.save()
return JsonResponse({"code": 0, "msg": "success"})
else:
return JsonResponse({"code": -1, "msg": "not null"})
优化后的登陆接口
def login2(request): username = request.POST.get(“username”) # email + password ; phone+password password = request.POST.get(“password”) if username and password: user = models.NewUser.objects.filter(Q(email=username) | Q(phone=username)) if not user.exists(): return JsonResponse({“code”: -1, “msg”: “user not exists”}) if user.first().password != md5(password): return JsonResponse({“code”: -1, “msg”: “password error”})
#todo:这里要校验当前用户是否已经登录,如果已经登录,那么直接返回token (用来解决重复登陆存储多个token的问题)
user_key = "session_wxj:%s"%user.first().phone
# 登陆时,给Redis中存储两条记录 (用户名:token)(token:用户信息)
#
r = django_redis.get_redis_connection()
redis_token = r.get(user_key)
if redis_token:# 如果Redis中有这个用户的登陆记录就返回上一次登陆获取的token
return JsonResponse({"code": 0, "msg": "login success", "token": redis_token.decode()})
#
token = md5(str(time.time()) + username) # 如果没有登陆记录,就重新返回新的token
# user_dict = json.dumps(model_to_dict(user.first())) # 被优化的代码
pickle_user_obj = pickle.dumps(user.first()) # 优化的代码:直接把 模型类的实例对象 以二进制对象 存入变量中
r = django_redis.get_redis_connection()
expire_time = 60 * 60 * 24 * 1 # session的过期时间
#
r.set(user_key, token, expire_time)# 登陆时,给Redis中存储两条记录 (用户名:token)(token:用户信息)
#
# r.set(token, user_dict, expire_time) # 被优化的代码
r.set(token,pickle_user_obj,expire_time) # 优化的代码:直接 模型类的实例对象 以二进制形式存入Redis中
return JsonResponse({"code": 0, "msg": "login success", "token": token})
else:
return JsonResponse({"code": -1, "msg": "not null"})
def md5(s): s = str(s) m = hashlib.md5(s.encode()) return m.hexdigest()
<a name="H0M66"></a>
# 2、优化后的中间件
- 将登陆后,Redis中的用户信息,通过pickle再次用request对象的自定义属性去接收
```python
import pickle
from django.middleware.common import MiddlewareMixin
from django.http.response import HttpResponse, JsonResponse
import django_redis
import json
no_login_urls = ["login", "register", "admin"]
class TokenMiddleWare(MiddlewareMixin):
def check_not_url(self, path): # /api/login
for url in no_login_urls:
if url in path:
# 模糊匹配,URL中包含这个就不校验token
return True
def process_request(self, request):
# 执行路由之前被调用
login_tag = self.check_not_url(request.path_info)
if login_tag != True:
token = request.GET.get("token")
if not token:
return JsonResponse({"code": -1, "msg": "没有传token"})
r = django_redis.get_redis_connection()
login_user = r.get(token)
if not login_user:
return JsonResponse({"code": -1, "msg": "token已失效"})
# request.user = json.loads(login_user) # 给request对象里面增加user属性
request.user = pickle.loads(login_user) # 优化后:request对象的user属性 就是 模型类的实例对象了,
# 可以从这个对象身上查到用户所有信息
# token = reuqest.headers.get("token")
# request.path_info /login /api/register
# 1、先判断url是否需要登录,需要登录才校验token
# 2、在判断是否传了token
# 3、再判断在redis里面是否有token
# def process_response(self,request,response):
# print("process_response")
# response["aaaaa"] = "111111"
# return response
# def process_exception(self,request,exception):
# print("exception",exception)
# return