SpringCloud+Tornado基于jwt實現(xiàn)請求安全校驗功能
項目背景
在實際項目中,Tornado
項目作為一個微服務(wù)納入SpringCloud
體系,該過程中涉及到Tornado
與Spring
體系的安全驗證,也就是權(quán)限調(diào)用校驗,在該項目中Tornado
是通過SpringCloud
中的Feign
調(diào)用的,經(jīng)過一系列實驗,最后選用jwt
來實現(xiàn)這個權(quán)限效驗的過程。
實現(xiàn)思路
用戶進行登陸認證(后臺微服務(wù)),認證成功后調(diào)用Tornado
項目的認證接口生成token
,該值返回到后臺微服務(wù)保存在會話中,下一次請求時帶上該token
值讓服務(wù)器進行校驗,校驗成功則返回正常的響應(yīng),否則返回錯誤信息。
項目結(jié)構(gòu)
common - authServer.py是認證接口 common - basicServer.py是示例接口 handlers - baseHandler.py中放了兩種校驗方式,會在basicServer.py的調(diào)用示例中貼出 utils - jwtUtils.py是生成與校驗token的 utils - responseUtils.py是返回結(jié)果工具類
具體實現(xiàn)
jwtUtils.py
# -*- coding:utf-8 -*- import jwt import datetime from jwt import exceptions from utils.responseUtils import JsonUtils JWT_SALT = '1qazxdr5' def create_token(payload, timeout=12): """ 創(chuàng)建token :param payload: 例如:{'user_id':1,'username':'xxx@xxx.xx'}用戶信息 :param timeout: token的過期時間,默認20分鐘 :return: """ headers = { 'typ': 'jwt', 'alg': 'HS256' } payload['exp'] = datetime.datetime.utcnow() + datetime.timedelta(minutes=timeout) result = jwt.encode(payload=payload, key=JWT_SALT, algorithm="HS256", headers=headers).decode('utf-8') return result def parse_payload(token): """ 對token進行校驗并獲取payload :param token: :return: """ try: verified_payload = jwt.decode(token, JWT_SALT, True) print(verified_payload) return JsonUtils.success('認證通過') except exceptions.ExpiredSignatureError: return JsonUtils.noAuth('token已失效') except jwt.DecodeError: return JsonUtils.noAuth('token認證失敗') except jwt.InvalidTokenError: return JsonUtils.noAuth('非法的token')
baseHandler.py
# -*- coding:utf-8 -*- import functools import json import tornado.web from utils import jwtUtils from utils.responseUtils import JsonUtils # 方式一:authenticated 裝飾器 def authenticated(method): @functools.wraps(method) def wrapper(self, *args, **kwargs): """ 這里調(diào)用的是 current_user 的 get 方法(property裝飾), """ # 通過token請求頭傳遞token head = self.request.headers token = head.get("token", "") if not token: self.write(JsonUtils.noAuth("未獲取到token請求頭")) self.set_header('Content-Type', 'application/json') return result = json.loads(jwtUtils.parse_payload(token)) # 將json解碼 print(result) token_msg = json.dumps(result) if result['sta'] != '00': self.write(token_msg) self.set_header('Content-Type', 'application/json') return return method(self, *args, **kwargs) return wrapper # 方式二:進行預(yù)設(shè) 繼承tornado的RequestHandler class BaseHandler(tornado.web.RequestHandler): def prepare(self): super(BaseHandler, self).prepare() def set_default_headers(self): super().set_default_headers() # 進行token校驗,繼承上面的BaseHandler class TokenHandler(BaseHandler): def prepare(self): # 通過token請求頭傳遞token head = self.request.headers token = head.get("token","") if not token: self.authMsg = json.dumps(JsonUtils.noAuth("未獲取到token請求頭")) result = json.loads(jwtUtils.parse_payload(token)) # 將json解碼 print(result) if result['sta'] != '00': self.isAuth = False else: self.isAuth = True self.authMsg = json.dumps(result)
authServer.py
import tornado.web from utils import jwtUtils from utils.responseUtils import JsonUtils class authHandler(tornado.web.RequestHandler): def post(self, *args, **kwargs): """ 安全認證接口 :param args: :param kwargs: :return: """ username = self.get_argument("username") print("authHandler:" + username) if not username: self.write(JsonUtils.error("參數(shù)異常")) else: token = jwtUtils.create_token({"username": username}) print("token:" + token) self.write(JsonUtils.success(token)) self.set_header('Content-Type', 'application/json')
basicServer.py
import tornado.web import json from pandas.core.frame import DataFrame from handlers import baseHandler from utils.responseUtils import JsonUtils from handlers.baseHandler import authenticated class StringHandler(baseHandler.TokenHandler, tornado.web.RequestHandler): """ *** TokenHandler驗證,對應(yīng)baseHandler.py中的方式二 *** """ def get(self): username = self.get_argument('username', 'Hello') # 權(quán)限認證通過 if self.isAuth: self.write(JsonUtils.success(username)) else: self.write(self.authMsg)) self.set_header('Content-Type', 'application/json') class TestHandler(tornado.web.RequestHandler): """ *** authenticated驗證,對應(yīng)baseHandler.py中的方式一 *** """ @authenticated def post(self): username = self.get_argument('username', 'Hello') self.write(JsonUtils.success(username)) self.set_header('Content-Type', 'application/json')
responseUtils.py
from tornado.escape import json_encode, utf8 class JsonUtils(object): @staticmethod def success(response): """ 正確返回 :param response: 返回結(jié)果 :return: string, {"message": "ok", "sta": "00", "data": } """ return json_encode({"message": "ok", "sta": "00", "data": response}) @staticmethod def info(message): """ 提示返回 :param message: 提示信息 :return: string, """ return json_encode({"message": str(message), "sta": "99001", "data": None}) @staticmethod def error(message): """ 錯誤返回 :param message: 錯誤信息 :return: string, """ return json_encode({"message": str(message), "sta": "9999", "data": None}) @staticmethod def noAuth(message): """ 無權(quán)限返回 :param message: 錯誤信息 :return: string, """ return json_encode({"message": str(message), "sta": "403", "data": None})
下面是一些調(diào)用的結(jié)果圖示:
.end
到此這篇關(guān)于SpringCloud+Tornado基于jwt實現(xiàn)請求安全校驗的文章就介紹到這了,更多相關(guān)SpringCloud+Tornado實現(xiàn)請求安全校驗內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java阻塞隊列必看類:BlockingQueue快速了解大體框架和實現(xiàn)思路
這篇文章主要介紹了Java阻塞隊列必看類:BlockingQueue快速了解大體框架和實現(xiàn)思路,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10SpringBoot請求發(fā)送與信息響應(yīng)匹配實現(xiàn)方法介紹
這篇文章主要介紹了SpringBoot請求發(fā)送與信息響應(yīng)匹配實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-10-10Java通過動態(tài)規(guī)劃設(shè)計股票買賣最佳時機
動態(tài)規(guī)劃可謂是大名鼎鼎,筆試面試中的高頻考點,也是重點難點,動態(tài)規(guī)劃類型題目靈活多變,難度系數(shù)也相對較高,往往我們做不好動態(tài)規(guī)劃的題目就會與心儀的offer失之交臂,本篇文章我們就一起來研究一下動態(tài)規(guī)劃設(shè)計股票買賣最佳時機2022-10-10Java基于FFmpeg實現(xiàn)Mp4視頻轉(zhuǎn)GIF
FFmpeg是一套可以用來記錄、轉(zhuǎn)換數(shù)字音頻、視頻,并能將其轉(zhuǎn)化為流的開源計算機程序。本文主要介紹了在Java中如何基于FFmpeg進行Mp4視頻到Gif動圖的轉(zhuǎn)換,感興趣的小伙伴可以了解一下2022-11-11Java 并發(fā)編程學(xué)習(xí)筆記之Synchronized簡介
雖然多線程編程極大地提高了效率,但是也會帶來一定的隱患。比如說兩個線程同時往一個數(shù)據(jù)庫表中插入不重復(fù)的數(shù)據(jù),就可能會導(dǎo)致數(shù)據(jù)庫中插入了相同的數(shù)據(jù)。今天我們就來一起討論下線程安全問題,以及Java中提供了什么機制來解決線程安全問題。2016-05-05servlet生命周期_動力節(jié)點Java學(xué)院整理
這篇文章主要為大家詳細介紹了servlet生命周期的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07