iT邦幫忙

2021 iThome 鐵人賽

DAY 8
0
Modern Web

30天肝出購物網站系列 第 8

Day08:08 - User服務(3) - 後端 - JWT token、修改個人資料

Hej,我是Charlie!
在Day07當中,我們完成了基本的登入跟登出,而在今天我們將完成JWT token跟修改個人資料的部分。

================================◉‿◉=================================

首先來介紹JWT是什麼吧。
JWT的全名是Json Web Token,可以使用密碼或者金鑰進行簽章,適合用在授權的部分。
JWT可以用一些演算法來加密,這次我們要用的是SHA256,而JWT基本的結構如下:

  1. header
  2. payload
  3. signature/encryption data

其中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:
https://ithelp.ithome.com.tw/upload/images/20210922/20141666qnzbR5iAs5.png

可以看到返回了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:
https://ithelp.ithome.com.tw/upload/images/20210922/20141666mut5HwlDbl.png

這時我們必須帶AUTHORIZATION頭,在POSTMAN的header地方編輯,再發送即可更新成功:
https://ithelp.ithome.com.tw/upload/images/20210922/20141666bwpThagDKL.png
https://ithelp.ithome.com.tw/upload/images/20210922/20141666VIdU63yezI.png

================================◉‿◉=================================

Day08結束了!在今天我們完成了JWT token跟修改個人資料的後端的部分,明天我們將完成前端的部分,See ya next day!


上一篇
Day07:07 - User服務(2) - 前端 - 註冊、登入、JS正則表達式
下一篇
Day09:09 - User服務(4) - 前端 - JWT token、修改個人資料
系列文
30天肝出購物網站30

尚未有邦友留言

立即登入留言