Hej,我是Charlie!
在Day07當中,我們完成了基本的登入跟登出,而在今天我們將完成JWT token跟修改個人資料的部分。
================================◉‿◉=================================
首先來介紹JWT是什麼吧。
JWT的全名是Json Web Token,可以使用密碼或者金鑰進行簽章,適合用在授權的部分。
JWT可以用一些演算法來加密,這次我們要用的是SHA256,而JWT基本的結構如下:
其中header的部分是聲明JWT用的是何種算法,而payload指的是JWT中的資料,而signature / encryption data指的是簽章的部分。
而這次我們要使用PyJWT,這次的PyJWT用法如下:
以下取自PyJWT documentation
加密:jwt.encode( {"some": "payload"}, "secret", algorithm="HS256")
解密:jwt.decode(encoded_jwt, "secret", algorithms=["HS256"])
首先是key的部分,這裡會使用GRC Generator產生:
https://www.grc.com/passwords.htm
這個網站刷新過後就會有新的密碼,所以我們可以取得一組高強度的密碼,作為JWT的key使用。
首先先新增tools\token.py,並在token.py當中新增def make_token,先指定key跟expire_time:
import jwt
import time
def make_token(data):
key = "use your own secret key"
now = time.time()
expiretime = 60 * 60
接著創立payload,並且使用jwt.encode:
payload = {
"username": data.username,
"expire": now + expiretime
}
return jwt.encode(payload,key,algorithm = 'HS256')
所以在login這邊,我們就可以返回我們的JWT:
from tools.token import make_token
token = make_token(user)
return R.ok({"message":"Authorize success","token":token})
加完之後,就可以測試login:
可以看到返回了token,同樣的也加在註冊,註冊成功後返回token,讓使用者可以直接登入:
token = make_token(user)
return R.created({"message":"User created","token":token})
成功製作完token之後,要做檢查token的部分。檢查token的部分由於是某些方法、大部分請求都要使用到的,所以我們建立一個裝飾器,用來裝飾大部分的視圖:
import jwt
from users.models import User
from tools.R import R
def logincheck(*methods):
def _logincheck(func):
def wrapper(request,*args,**kwargs):
token = request.META.get("HTTP_AUTHORIZATION")
if request.method not in methods:
return func(request,*args,**kwargs)
if not token:
return R.badRequest("no token")
try:
key = 'replace with your own key'
res = jwt.decode(token, key, algorithms=['HS256'])
except jwt.ExpiredSignatureError:
return R.badRequest("login again")
except Exception as e:
return R.internalServerError("Internal Server Error")
username = res['username']
user = User.objects.filter(name = username)
if not user:
return R.badRequest("User does not exist")
request.user = user
return func(request,*args,**kwargs)
return wrapper
return _logincheck
如此一來,我們就可以將logincheck裝飾在users上:
from tools.login_check import logincheck
@logincheck('PUT','DELETE')
def users(request):
接著是個人資料修改的部分,這裡是PUT方法,如果是PUT的話就判別用戶存不存在,存在就進行修改操作:
elif request.method == "PUT":
res = request.body
user = UserModel()
user.fromJson(res)
fuser = User.objects.filter(name = user.username)
if not fuser:
return R.badRequest("User does not exist")
fuser.update(
name = user.username,
phone = user.phone,
address = user.address
)
return R.ok("Update success")
如果我們用POSTMAN測試的話,直接發送會顯示no token:
這時我們必須帶AUTHORIZATION頭,在POSTMAN的header地方編輯,再發送即可更新成功:
================================◉‿◉=================================
Day08結束了!在今天我們完成了JWT token跟修改個人資料的後端的部分,明天我們將完成前端的部分,See ya next day!