不要妄想事情變得簡單往堡,還是期待自己能做的更好吧!
總結(jié):
- 網(wǎng)絡(luò)安全是一個很有前途的方向久信;
- session和cookie是解決無狀態(tài)的問題(用戶來了);
- 用戶密碼加密不在用戶端加密蝴猪;
用戶功能設(shè)計與實(shí)現(xiàn)
提供用戶注冊處理
- 提供用戶登錄處理
- 提供路由配置
1. 用戶登錄接口設(shè)計
接收用戶通過POST方法提交的登錄信息调衰,提交的數(shù)據(jù)是JSON格式數(shù)據(jù)
Restful=URL+METHOD URL:/user/reg ; METHOD:POST
從user表中email找出匹配的一條記錄,驗(yàn)證密碼是否正確自阱。
驗(yàn)證通過說明是合法用戶登錄嚎莉,顯示歡迎頁面。
驗(yàn)證失敗返回錯誤狀態(tài)碼沛豌,例如4xx
{
"password":"abc",
"email":"wayne@magedu.com"
}
1.1 路由配置
from django.conf.urls import url
from .views import reg,show,login
urlpatterns = [
url(r'^reg$',reg),
url(r'^login$',login),
url(r'^show$',show),
]
1.2 登錄代碼
from django.http import JsonResponse,HttpRequest,HttpResponseBadRequest
import simplejson,jwt,bcrypt
from .models import User
from django.db.models import Q
from django.conf import settings
def gen_token(user_id): # 生成令牌趋箩;
key = settings.SECRET_KEY
return JsonResponse({
'token':jwt.encode({'user_id':user_id},key,'HS256').decode()
},status=201)
# register
def reg(request:HttpRequest):
print(request.body)
try:
payload = simplejson.loads(request.body) # 用戶數(shù)據(jù)Json化 提交;
print(type(settings))
email = payload['email'] # 提取內(nèi)容
query = User.objects.filter(email=email) # 看email是否已經(jīng)存在加派;
if query.first(): # 查一下: email 如果存在叫确,則return error;
print('============================')
return HttpResponseBadRequest('用戶名已存在')
# 用戶名不存在,繼續(xù)向下芍锦;
name = payload['name'] #
password = payload['password']
user = User()
user.email = email
user.name = name
user.password = bcrypt.hashpw(password.encode(),bcrypt.gensalt()) # 密碼采用bcrypt加密竹勉;
try:
user.save() #保存到數(shù)據(jù)庫test,唯一鍵約束
return gen_token(user.id) # 保存數(shù)據(jù)后返回一個令牌數(shù)據(jù)回去;
# 可以返回user_id status=201(注冊成功 重新登錄) 或者 token(登錄)
except Exception as e:
return JsonResponse({'reason':'asdaf'},status=400)
except Exception as e:
print(e)
return HttpResponseBadRequest('參數(shù)錯誤')
def login(request:HttpRequest):
try:
payload = simplejson.loads(request.body)
email = payload['email']
password = payload['password']
user = User.objects.filter(email=email).first()
if user:
if bcrypt.checkpw(password.encode(),user.password.encode()):
return gen_token(user.id)
else:
return HttpResponseBadRequest('登錄失敗3')
else:
return HttpResponseBadRequest('登錄失敗1')
except Exception as e: # 記錄登錄日志娄琉;
print(e)
return HttpResponseBadRequest('登錄失敗2')
def show(request): # 方法的使用方式各不相同次乓;
users = User.objects.all()
print(users.values())# objects
return JsonResponse({})
#---------------------------------------------------
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo4fQ.-c9iliH6cV9PmsnxL-73ptlIetVsWvA-dUG5MBcboOU"
}
from django.http import JsonResponse,HttpRequest,HttpResponseBadRequest
import simplejson,jwt,bcrypt
from .models import User
from django.db.models import Q
from django.conf import settings
def gen_token(user_id): # 生成令牌;
key = settings.SECRET_KEY
return jwt.encode({'user_id':user_id},key,'HS256').decode()
# register
def reg(request:HttpRequest):
print(request.body)
try:
payload = simplejson.loads(request.body) # 用戶數(shù)據(jù)Json化 提交孽水;
print(type(settings))
email = payload['email'] # 提取內(nèi)容
query = User.objects.filter(email=email) # 看email是否已經(jīng)存在票腰;
if query.first(): # 查一下: email 如果存在,則return error;
print('============================')
return HttpResponseBadRequest('用戶名已存在')
# 用戶名不存在女气,繼續(xù)向下杏慰;
name = payload['name'] #
password = payload['password']
user = User()
user.email = email
user.name = name
user.password = bcrypt.hashpw(password.encode(),bcrypt.gensalt()) # 密碼采用bcrypt加密;
try:
user.save() #保存到數(shù)據(jù)庫test,唯一鍵約束
return JsonResponse({
'user_id':user.id
}) # 保存數(shù)據(jù)后返回一個令牌數(shù)據(jù)回去炼鞠;
# 可以返回user_id status=201(注冊成功 重新登錄) 或者 token(登錄)
except Exception as e:
return JsonResponse({'reason':'asdaf'},status=400)
except Exception as e:
print(e)
return HttpResponseBadRequest('參數(shù)錯誤')
def login(request:HttpRequest):
try:
payload = simplejson.loads(request.body)
email = payload['email']
password = payload['password']
user = User.objects.filter(email=email).first()
if user:
if bcrypt.checkpw(password.encode(),user.password.encode()):
token = gen_token(user.id)
res = JsonResponse({
'user':{
'user_id': user.id,
'name': user.name,
'email': user.email
}, 'token': token
})
res.set_cookie('jwt',token) # 演示 如何 set_cookie
return res
else:
return HttpResponseBadRequest('登錄失敗3')
else:
return HttpResponseBadRequest('登錄失敗1')
except Exception as e: # 記錄登錄日志缘滥;
print(e)
return HttpResponseBadRequest('登錄失敗2')
def show(request): # 方法的使用方式各不相同;
users = User.objects.all()
print(users.values())# objects
return JsonResponse({})
# --------------------------------------------------------
{
"user": {
"user_id": 8,
"name": "sunny",
"email": "sunny@magedu.com"
},
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo4fQ.-c9iliH6cV9PmsnxL-73ptlIetVsWvA-dUG5MBcboOU"
}
2. 認(rèn)證接口
如何獲取瀏覽器提交的token信息簇搅?
1完域、使用Header中的Authorization
通過這個header增加token信息。
通過header發(fā)送數(shù)據(jù)瘩将,方法可以是Post、Get2.自定義header
JWT來發(fā)送token
我們選擇第二種方式
認(rèn)證
基本上所有的業(yè)務(wù)都需要認(rèn)證用戶的信息。
在這里比較時間戳姿现,如果過期肠仪,就直接拋未認(rèn)證401,客戶端收到后就該直接跳轉(zhuǎn)到登錄頁备典。
如果沒有提交userid咪辱, 就直接重新登錄饲嗽。如果用戶查到了, 填充user對象。
request時間戳比較->userid比較>向后執(zhí)行
def show(request): # 方法的使用方式各不相同吮旅;
token = request.META.get('HTTP_JWT', None)
# print(list(filter(lambda x: x.lower().endswith('jwt'),meta))) #查詢 http_jwt
print(token)
key = settings.SECRET_KEY
try:
jwt.decode(token,key,algorithms=['HS256']) # 解失敗,被改過被廓;接成功党觅;沒改過;
print(payload)
except Exception as e:
print(e)
return HttpResponseBadRequest('用戶名密碼錯誤')
return JsonResponse({'status':'ok'})
from django.http import JsonResponse,HttpRequest,HttpResponseBadRequest
import simplejson,jwt,bcrypt,datetime
from .models import User
from django.db.models import Q
from django.conf import settings
def gen_token(user_id): # 生成令牌倚喂;
key = settings.SECRET_KEY
return jwt.encode({'user_id':user_id,
'timestamp':int(datetime.datetime.now().timestamp())
},key,'HS256').decode()
# register
def reg(request:HttpRequest):
print(request.body)
try:
payload = simplejson.loads(request.body) # 用戶數(shù)據(jù)Json化 提交每篷;
print(type(settings))
email = payload['email'] # 提取內(nèi)容
query = User.objects.filter(email=email) # 看email是否已經(jīng)存在;
if query.first(): # 查一下: email 如果存在端圈,則return error;
print('============================')
return HttpResponseBadRequest('用戶名已存在')
# 用戶名不存在焦读,繼續(xù)向下;
name = payload['name'] #
password = payload['password']
user = User()
user.email = email
user.name = name
user.password = bcrypt.hashpw(password.encode(),bcrypt.gensalt()) # 密碼采用bcrypt加密舱权;鹽一直在變矗晃,強(qiáng)加密;
try:
user.save() #保存到數(shù)據(jù)庫test,唯一鍵約束
return JsonResponse({
'user_id':user.id
}) # 保存數(shù)據(jù)后返回一個令牌數(shù)據(jù)回去宴倍;
# 可以返回user_id status=201(注冊成功 重新登錄) 或者 token(登錄)
except Exception as e:
return JsonResponse({'reason':'asdaf'},status=400)
except Exception as e:
print(e)
return HttpResponseBadRequest('參數(shù)錯誤')
def login(request:HttpRequest):
try:
payload = simplejson.loads(request.body)
email = payload['email']
password = payload['password']
user = User.objects.filter(email=email).first()
if user: # 登錄成功张症,返回信息
if bcrypt.checkpw(password.encode(),user.password.encode()):
token = gen_token(user.id)
res = JsonResponse({
'user':{
'user_id': user.id,
'name': user.name,
'email': user.email
}, 'token': token
})
res.set_cookie('jwt',token) # 演示 如何 set_cookie
return res
else:
return HttpResponseBadRequest('登錄失敗3')
else:
return HttpResponseBadRequest('登錄失敗1')
except Exception as e: # 記錄登錄日志;
print(e)
return HttpResponseBadRequest('登錄失敗2')
# 誰認(rèn)證就給誰加裝飾器啊楚;
def auth(view_func):
def wrapper(request:HttpRequest):
token = request.META.get('HTTP_JWT', None) # 拿到http_jwt 字典的值
# print(list(filter(lambda x: x.lower().endswith('jwt'),meta))) #查詢 http_jwt
print(token)
key = settings.SECRET_KEY
try:
print('=============================')
jwt.decode(token, key, algorithms=['HS256']) # 解失敗吠冤,被改過;接成功恭理;沒改過拯辙;
print(payload)
user = User.objects.filter(pk=payload['user_id']).first() # 查詢一次數(shù)據(jù)庫;
# user = User.objects.filter(pk=payload['user_id']).filter(isactive=True).first()
if user: # 拿到user,
request.user = user #request 動態(tài)添加屬性颜价;
ret = view_func(request)
return ret
else:
return HttpResponseBadRequest('1用戶名密碼錯誤')
except Exception as e:
print(e)
return HttpResponseBadRequest('2用戶名密碼錯誤')
return wrapper
@auth # 認(rèn)證攔截
def show(request): # 方法的使用方式各不相同涯保;
print(request.user,'---------------------------')
return JsonResponse({'status':'ok'})
#----------------------------------------------------------
{
"user": {
"user_id": 8,
"name": "sunny",
"email": "sunny@magedu.com"
},
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo4LCJ0aW1lc3RhbXAiOjE1OTc1MDE3NDIuODYxNzA3fQ.jOOTyLE6GeXMmdCmYhGmw5fjj2BQoHWPmtx8ppvYUrU"
}