JWT 多網站單點登錄,放棄session


多個網站之間的登錄信息共享, 基於cookie - session的登錄認證方式跨域等比較復雜。采用基於算法的認證方式, JWT(json web token)的方式。

 

------------------------------------------------------------------------------------------

參考:

http://www.tuicool.com/articles/IRJnaa

https://coderwall.com/p/8wrxfw/goodbye-php-sessions-hello-json-web-tokens

在JavaScript前端技術大行其道的今天,我們通常只需在后台構建API提供給前端調用,並且后端僅僅設計為給前端移動App調用。用戶認證是Web應用的重要組成部分,基於API的用戶認證有兩個最佳解決方案 —— OAuth 2.0 和JWT(JSON Web Token)。

1、JWT定義及其組成

JWT(JSON Web Token)是一個非常輕巧的規范。這個規范允許我們使用JWT在用戶和服務器之間傳遞安全可靠的信息。

一個JWT實際上就是一個字符串,它由三部分組成,頭部、載荷與簽名。

載荷(Payload)

我們先將用戶認證的操作描述成一個JSON對象。其中添加了一些其他的信息,幫助今后收到這個JWT的服務器理解這個JWT。

{
    "sub": "1", "iss": "http://localhost:8000/auth/login", "iat": 1451888119, "exp": 1454516119, "nbf": 1451888119, "jti": "37c107e4609ddbcc9c096ea5ee76c667" }

這里面的前6個字段都是由JWT的標准所定義的。

  • sub: 該JWT所面向的用戶
  • iss: 該JWT的簽發者
  • iat(issued at): 在什么時候簽發的token
  • exp(expires): token什么時候過期
  • nbf(not before):token在此時間之前不能被接收處理
  • jti:JWT ID為web token提供唯一標識

這些定義都可以在 標准 中找到。

將上面的JSON對象進行base64編碼可以得到下面的字符串:

eyJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWx
ob3N0OjgwMDFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUxODg4MTE5LCJleHAiOjE0NTQ1MTYxMTksIm5iZiI6MTQ1MTg4OD
ExOSwianRpIjoiMzdjMTA3ZTQ2MDlkZGJjYzljMDk2ZWE1ZWU3NmM2NjcifQ

這個字符串我們將它稱作JWT的Payload(載荷)。

如果你使用Node.js,可以用Node.js的包base64url來得到這個字符串:

var base64url = require('base64url') var header = { "from_user": "B", "target_user": "A" } console.log(base64url(JSON.stringify(header)))

注:Base64是一種編碼,也就是說,它是可以被翻譯回原來的樣子來的。它並不是一種加密過程。

頭部(Header)

JWT還需要一個頭部,頭部用於描述關於該JWT的最基本的信息,例如其類型以及簽名所用的算法等。這也可以被表示成一個JSON對象:

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

在這里,我們說明了這是一個JWT,並且我們所用的簽名算法(后面會提到)是HS256算法。

對它也要進行Base64編碼,之后的字符串就成了JWT的Header(頭部):

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

簽名(簽名)

將上面的兩個編碼后的字符串都用句號.連接在一起(頭部在前),就形成了:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWx ob3N0OjgwMDFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUxODg4MTE5LCJleHAiOjE0NTQ1MTYxMTksIm5iZiI6MTQ1MTg4OD ExOSwianRpIjoiMzdjMTA3ZTQ2MDlkZGJjYzljMDk2ZWE1ZWU3NmM2NjcifQ

最后,我們將上面拼接完的字符串用HS256算法進行加密。在加密的時候,我們還需要提供一個密鑰(secret):

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

這樣就可以得到我們加密后的內容:

wyoQ95RjAyQ2FF3aj8EvCSaUmeP0KUqcCJDENNfnaT4

這一部分又叫做簽名。

最后將這一部分簽名也拼接在被簽名的字符串后面,我們就得到了完整的JWT:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWx ob3N0OjgwMDFcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUxODg4MTE5LCJleHAiOjE0NTQ1MTYxMTksIm5iZiI6MTQ1MTg4OD ExOSwianRpIjoiMzdjMTA3ZTQ2MDlkZGJjYzljMDk2ZWE1ZWU3NmM2NjcifQ.wyoQ95RjAyQ2FF3aj8EvCSaUmeP0KUqc

--------------------------------------

Goodbye PHP Sessions, Hello JSON Web Tokens

REST API's are meant to be stateless. What that means is that each request from a client should include all the information needed to process the request. In other words, if you are writing a REST API in PHP then you should not be using $_SESSION to store data about the client's session. But then how do we remember if a client is logged in or anything else about their state? The only possibility is that the client must be tasked with keeping track of the state. How could this ever be done securely? The client can't be trusted!

Enter JSON web tokens. A JSON web token is a bit of JSON, perhaps something that looks like this:

{ "user": "alice", "email": "test@nospam.com" }

Of course, we can't just give this to a client and have them give it back to us without some sort of assurance that it hasn't been tampered with. After all, what if they edit the token as follows:

{ "user": "administrator", "email": "test@nospam.com" }

The solution to this is that JSON web tokens are signed by the server. If the client tampers with the data then the token's signature will no longer match and an error can be raised.

The JWT PHP class makes this easy to do. For example, to create a token after the client successfully logs in, the following code could be used:

$token = array(); $token['id'] = $id; echo JWT::encode($token, 'secret_server_key');

And then on later API calls the token can be retrieved and verified by this code:

$token = JWT::decode($_POST['token'], 'secret_server_key'); echo $token->id;

If the token has been tampered with then $token will be empty there will not be an id available. The JWT class makes sure that invalid data is never made available. If the token is tampered with, it will be unusable. Pretty simple stuff!

You can get the PHP JWT class as a single file from: https://github.com/rmcdaniel/angular-codeigniter-seed/blob/master/api/application/helpers/jwt_helper.php

as it is used by the AngularJS CodeIgniter Seed project:

https://github.com/rmcdaniel/angular-codeigniter-seed

or the original code from:

https://github.com/luciferous/jwt

Written by Richard McDaniel


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM