django測試平臺開發,登入,驗證,退出
阿新 • • 發佈:2020-09-21
#驗證登入傳遞的資料是否符合規則,forms
### forms.py ###
# 不能用ModelForm
# 登入要驗證什麼? username password
class LoginForm(forms.Form,tools.ErrorFormat): #ErrorFormat--優化error返回的錯誤資訊 '''登陸驗證username,password''' username = forms.CharField(min_length=5,max_length=20,required=True) password = forms.CharField(min_length=6,max_length=20,required=True)def clean(self): print("self.errors",self.errors) print("self.cleaned_data",self.cleaned_data) if not self.errors: #繼續驗證賬號密碼是否正確 username = self.cleaned_data['username'] password = self.cleaned_data['password'] #使用者是否存在 qs = models.User.objects.filter(phone=username)if qs: user_obj = qs.first() if user_obj.check_password(password): self.cleaned_data['user'] =user_obj return self.cleaned_data else: self.add_error('password', '密碼錯誤') else: self.add_error('username','使用者不存在') return self.cleaned_data
##### tools.py ###
class ErrorFormat:
@property
def error_format(self):
errors_data = self.errors.get_json_data()
print("errors_data",errors_data)
error_list = []
for k,v in errors_data.items():
error_list.append(k+':'+v[0].get("message"))
return ','.join(error_list)
#2-views中寫介面邏輯,連線並寫入redis
class Login(View): def post(self, request): ''' 1、驗證前端傳遞的資料是否符合規則,forms 2、登入成功需要有標示,標示(token)存到 redis :param request: :return: ''' form_obj = forms.LoginForm(request.POST) if form_obj.is_valid(): # 驗證通過的資料 代表登入成功 # 登入成功需要有標示,標示(token)存到 redis form_data = form_obj.cleaned_data # token 生成方式 使用者名稱 + 時間戳 + MD5 username = form_data.get('username') tmp_token = '%s%s' % (username, time.time()) # md5 用 tools提供工具 token = tools.md5(tmp_token) # 存 token的時候 token 應該key user = form_obj.cleaned_data['user'] # 安裝 pip install django-redis # 獲取redis 連結 預設取配置檔案中 default redis = django_redis.get_redis_connection() # 引數1 是key 引數2 是value 引數3 是過期時間 單位秒 # {token:userobj} # pickle.dumps(user) 序列化資料,轉成 二進位制 redis.set(const.SESSION + token, pickle.dumps(user), const.EXIT_TIME) return NbResponse(token=token, user=user.name, user_id=user.id) else: return NbResponse(-1, form_obj.error_format)
### redis配置,setting###
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": {"max_connections": 100},
"PASSWORD": "dsx", # 密碼
# 這個redis是返回資料是bytes型別的,登入的時候user用pickle序列化的,存的是二進位制,取出來的也是二進位制
}
},
"redis2": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://118.24.3.40:6379/2",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": {"max_connections": 100, 'decode_responses': True},
# 這個redis配置,從redis裡面取到資料後會自動轉成字串,不是bytes型別
"PASSWORD": "HK139bc&*", # 密碼
}
}
}
#3-NbResponse對響應資料封裝 ,等同於重寫JsonResponse
from django.http import JsonResponse class NbResponse(JsonResponse): def __init__(self, code=200, msg='操作成功', **kwargs): data = {"code": code, "msg": msg} data.update(kwargs) super().__init__(data=data, json_dumps_params={"ensure_ascii": False})
#4-ursl配置
### 其它介面登入校驗token,中介軟體
class SessionMiddleware(MiddlewareMixin): # 增加 一個過濾的場景 # 預製一個 列表 列表用於儲存,那些介面可以不登入就訪問 setting中 :NO_LOGIN_LIST = ['login','register'] def check_url(self, path_info): for url in NO_LOGIN_LIST: # path_info 前端過來的路徑 /api/login # url NO_LOGIN_LIST login if url in path_info: # 當前訪問的介面路徑 在 NO_LOGIN_LIST 返回false 不做token驗證 return False return True def process_request(self, request): '''請求過來之後先走到的這裡''' # print("dir(request)",dir(request)) # 前端傳遞過來的token 會自動變成大寫,並且在前面增加HTTP # print("request.META.get('HTTP_TOKEN')",request.META.get('HTTP_TOKEN')) print('request.path_info', request.path_info) if self.check_url(request.path_info): token = request.META.get('HTTP_TOKEN') if token: redis = django_redis.get_redis_connection() b_data = redis.get(const.SESSION + token) if b_data: data = pickle.loads(b_data) # 將當前的登入資訊 儲存到request當中 request.user = data request.user_id = data.id request.token = token else: return NbResponse(-1, '請登入') else: return NbResponse(-1, '請登入')
##登出,刪除token
class Logout(View): def post(self, request): redis = django_redis.get_redis_connection() redis.delete(const.SESSION + request.token) return NbResponse()