国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
使用 JWT 讓你的 RESTful API 更安全

傳統(tǒng)的 cookie-session 機制可以保證的接口安全,在沒有通過認證的情況下會跳轉(zhuǎn)至登入界面或者調(diào)用失敗。

在如今 RESTful 化的 API 接口下,cookie-session 已經(jīng)不能很好發(fā)揮其余熱保護好你的 API 。

更多的形式下采用的基于 Token 的驗證機制,JWT 本質(zhì)的也是一種 Token,但是其中又有些許不同。

什么是 JWT ?

JWT 及時 JSON Web Token,它是基于 RFC 7519 所定義的一種在各個系統(tǒng)中傳遞緊湊自包含的 JSON 數(shù)據(jù)形式。

  • 緊湊(Compact) :由于傳送的數(shù)據(jù)小,JWT 可以通過GET、POST 和 放在 HTTP 的 header 中,同時也是因為小也能傳送的更快。
  • 自包含(self-contained) : Payload 中能夠包含用戶的信息,避免數(shù)據(jù)庫的查詢。

JSON Web Token 由三部分組成使用 . 分割開:

  • Header
  • Payload
  • Signature

一個 JWT 形式上類似于下面的樣子:

xxxxx.yyyy.zzzz

Header 一般由兩個部分組成:

  • alg
  • typ

alg 是是所使用的 hash 算法例如 HMAC SHA256 或 RSA,typ 是 Token 的類型自然就是 JWT。

{  "alg": "HS256",  "typ": "JWT"}

然后使用 Base64Url 編碼成第一部分。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.<second part>.<third part>

Payload

這一部分是 JWT 主要的信息存儲部分,其中包含了許多種的聲明(claims)。

Claims 的實體一般包含用戶和一些元數(shù)據(jù),這些 claims 分成三種類型:reserved, public, 和 private claims。

  • (保留聲明)reserved claims :預(yù)定義的 一些聲明,并不是強制的但是推薦,它們包括 iss (issuer), exp (expiration time), sub (subject),aud(audience) 等。

    這里都使用三個字母的原因是保證 JWT 的緊湊

  • (公有聲明)public claims : 這個部分可以隨便定義,但是要注意和 IANA JSON Web Token 沖突。

  • (私有聲明)private claims : 這個部分是共享被認定信息中自定義部分。

一個 Pyload 可以是這樣子的:

{  "sub": "1234567890",  "name": "John Doe",  "admin": true}

這部分同樣使用 Base64Url 編碼成第二部分。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.<third part>

Signature

在創(chuàng)建該部分時候你應(yīng)該已經(jīng)有了 編碼后的 Header 和 Payload 還需要一個一個秘鑰,這個加密的算法應(yīng)該 Header 中指定。

一個使用 HMAC SHA256 的例子如下:

HMACSHA256(  base64UrlEncode(header) + "." +  base64UrlEncode(payload),  secret)

這個 signature 是用來驗證發(fā)送者的 JWT 的同時也能確保在期間不被篡改。

所以,做后你的一個完整的 JWT 應(yīng)該是如下形式:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

注意被 . 分割開的三個部分

JSON Web Token 的工作流程

在用戶使用證書或者賬號密碼登入的時候一個 JSON Web Token 將會返回,同時可以把這個 JWT 存儲在local storage、或者 cookie 中,用來替代傳統(tǒng)的在服務(wù)器端創(chuàng)建一個 session 返回一個 cookie。

當(dāng)用戶想要使用受保護的路由時候,應(yīng)該要在請求得時候帶上 JWT ,一般的是在 header 的 Authorization 使用 Bearer 的形式,一個包含的 JWT 的請求頭的 Authorization 如下:

Authorization: Bearer <token>

這是一中無狀態(tài)的認證機制,用戶的狀態(tài)從來不會存在服務(wù)端,在訪問受保護的路由時候回校驗 HTTP header 中 Authorization 的 JWT,同時 JWT 是會帶上一些必要的信息,不需要多次的查詢數(shù)據(jù)庫。

這種無狀態(tài)的操作可以充分的使用數(shù)據(jù)的 APIs,甚至是在下游服務(wù)上使用,這些 APIs 和哪服務(wù)器沒有關(guān)系,因此,由于沒有 cookie 的存在,所以在不存在跨域(CORS, Cross-Origin Resource Sharing)的問題。

在 Flask 和 Express 中使用 JSON Web Token

JWT 在各個 Web 框架中都有 JWT 的包可以直接使用,下面使用 Flask 和 Express 作為例子演示。

下面會使用 httpie 作為演示工具:

HTTPie: HTTP client, a user-friendly cURL replacement.- Download a URL to a file:    http -d example.org- Send form-encoded data:    http -f example.org name="bob" profile-picture@"bob.png"- Send JSON object:    http example.org name="bob"- Specify an HTTP method:    http HEAD example.org- Include an extra header:    http example.org X-MyHeader:123- Pass a user name and password for server authentication:    http -a username:password example.org- Specify raw request body via stdin:    cat data.txt | http PUT example.org

Flask 中使用 JSON Web Token

這里的演示是 Flask-JWT 的 Quickstart內(nèi)容。

安裝必要的軟件包:

pip install flaskpip install Flask-JWT

一個簡單的 DEMO:

from flask import Flaskfrom flask_jwt import JWT, jwt_required, current_identityfrom werkzeug.security import safe_str_cmpclass User(object):    def __init__(self, id, username, password):        self.id = id        self.username = username        self.password = password    def __str__(self):        return "User(id="%s")" % self.idusers = [    User(1, "user1", "abcxyz"),    User(2, "user2", "abcxyz"),]username_table = {u.username: u for u in users}userid_table = {u.id: u for u in users}def authenticate(username, password):    user = username_table.get(username, None)    if user and safe_str_cmp(user.password.encode("utf-8"), password.encode("utf-8")):        return userdef identity(payload):    user_id = payload["identity"]    return userid_table.get(user_id, None)app = Flask(__name__)app.debug = Trueapp.config["SECRET_KEY"] = "super-secret"jwt = JWT(app, authenticate, identity)@app.route("/protected")@jwt_required()def protected():    return "%s" % current_identityif __name__ == "__main__":    app.run()

首先需要獲取用戶的 JWT:

% http POST http://127.0.0.1:5000/auth username="user1" password="abcxyz"             ~HTTP/1.0 200 OKContent-Length: 193Content-Type: application/jsonDate: Sun, 21 Aug 2016 03:48:41 GMTServer: Werkzeug/0.11.10 Python/2.7.10{    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6MSwiaWF0IjoxNDcxNzUxMzIxLCJuYmYiOjE0NzE3NTEzMjEsImV4cCI6MTQ3MTc1MTYyMX0.S0825N6IliQb65QoJfUXb3IGq-j9OVJpHBh-bcUz_gc"}

使用 @jwt_required() 裝飾器來保護你的 API

@app.route("/protected")@jwt_required()def protected():    return "%s" % current_identity

這時候你需要在 HTTP 的 header 中使用 Authorization: JWT <token> 才能獲取數(shù)據(jù)

% http http://127.0.0.1:5000/protected Authorization:"JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6MSwiaWF0IjoxNDcxNzUxMzIxLCJuYmYiOjE0NzE3NTEzMjEsImV4cCI6MTQ3MTc1MTYyMX0.S0825N6IliQb65QoJfUXb3IGq-j9OVJpHBh-bcUz_gc"HTTP/1.0 200 OKContent-Length: 12Content-Type: text/html; charset=utf-8Date: Sun, 21 Aug 2016 03:51:20 GMTServer: Werkzeug/0.11.10 Python/2.7.10User(id="1")

不帶 JWT 的時候會返回如下信息:

% http http://127.0.0.1:5000/protected                                                ~HTTP/1.0 401 UNAUTHORIZEDContent-Length: 125Content-Type: application/jsonDate: Sun, 21 Aug 2016 03:49:51 GMTServer: Werkzeug/0.11.10 Python/2.7.10WWW-Authenticate: JWT realm="Login Required"{    "description": "Request does not contain an access token",    "error": "Authorization Required",    "status_code": 401}

Express 中使用 JSON Web Token

Auth0 提供了 express-jwt 這個包,在 express 可以很容易的集成。

npm install express --savenpm install express-jwt --savenpm install body-parser --savenpm install jsonwebtoken --savenpm install shortid --save

本例子中只是最簡單的使用方法,更多使用方法參看 express-jwt

var express = require("express");var expressJwt = require("express-jwt");var bodyParser = require("body-parser");var jwt = require("jsonwebtoken");var shortid = require("shortid");var app = express();app.use(bodyParser.json());app.use(expressJwt({secret: "secret"}).unless({path: ["/login"]}));app.use(function (err, req, res, next) {  if (err.name === "UnauthorizedError") {    res.status(401).send("invalid token");  }});app.post("/login", function(req, res) {  var username = req.body.username;  var password = req.body.password;  if (!username) {    return res.status(400).send("username require");  }  if (!password) {    return res.status(400).send("password require");  }  if (username != "admin" && password != "password") {    return res.status(401).send("invaild password");  }  var authToken = jwt.sign({username: username}, "secret");  res.status(200).json({token: authToken});});app.post("/user", function(req, res) {  var username = req.body.username;  var password = req.body.password;  var country = req.body.country;  var age = req.body.age;  if (!username) {    return res.status(400).send("username require");  }  if (!password) {    return res.status(400).send("password require");  }  if (!country) {    return res.status(400).send("countryrequire");  }  if (!age) {    return res.status(400).send("age require");  }  res.status(200).json({    id: shortid.generate(),    username: username,    country: country,    age: age  })})app.listen(3000);

express-jwt 作為 express 的一個中間件,需要設(shè)置 secret 作為秘鑰,unless 可以排除某個接口。

默認的情況下,解析 JWT 失敗會拋出異常,可以通過以下設(shè)置來處理該異常。

app.use(expressJwt({secret: "secret"}).unless({path: ["/login"]}));app.use(function (err, req, res, next) {  if (err.name === "UnauthorizedError") {    res.status(401).send("invalid token");  }});

/login 忽略的 JWT 認證,通過這個接口獲取某個用戶的 JWT

% http POST http://localhost:3000/login username="admin" password="password" country="CN" age=22  HTTP/1.1 200 OKConnection: keep-aliveContent-Length: 143Content-Type: application/json; charset=utf-8Date: Sun, 21 Aug 2016 06:57:42 GMTETag: W/"8f-iMzAS1K5StDQgtNnVSvqtQ"X-Powered-By: Express{    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNDcxNzYyNjYyfQ.o5RFJB4GiR28HzXbSptU6MsPwW1tSXSDIjlzn7erG0M"}

不使用 JWT 的時候

% http POST http://localhost:3000/user username="hexiangyu" password="password"       ~HTTP/1.1 401 UnauthorizedConnection: keep-aliveContent-Length: 13Content-Type: text/html; charset=utf-8Date: Sun, 21 Aug 2016 07:00:02 GMTETag: W/"d-j0viHsPPu6FaNJ6cXoiFeQ"X-Powered-By: Expressinvalid token

使用 JWT 就可以成功調(diào)用

% http POST http://localhost:3000/user Authorization:"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNDcxNzYyNjYyfQ.o5RFJB4GiR28HzXbSptU6MsPwW1tSXSDIjlzn7erG0M" username="hexiangyu" password="password" country="CN" age=22HTTP/1.1 200 OKConnection: keep-aliveContent-Length: 66Content-Type: application/json; charset=utf-8Date: Sun, 21 Aug 2016 07:04:34 GMTETag: W/"42-YnGYuyDLxpVUexEGEcQj1g"X-Powered-By: Express{    "age": "22",    "country": "CN",    "id": "r1sFMCUc",    "username": "hexiangyu"}
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
使用Flask設(shè)計帶認證token的RESTful API接口[翻譯]
第 82 天:Python Web 開發(fā)之 JWT 簡介
使用json web token | 大前端
登錄鑒權(quán)的三種方式:token、jwt、session簡潔例子
Angular.JS 與node.JS架構(gòu)中基于token身份驗證實現(xiàn)。
Python Flask Restful token驗證
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服