iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 29
1
Modern Web

Iris這個在go語言上地表最快的網頁框架系列 第 29

iris的jwt

jwt

上一篇介紹了如何撰寫及使用middleware,而iris也有許多好用的middleware,所以本篇就來介紹一個好用的middleware jwt。

本文同步放置於此

jwt

介紹jwt這個middleware之前還是需要跟大家說明什麼是jwt,接下來再跟大家說明如何使用jwt這個middleware,所以接下來就是跟著這節奏先跟大家介紹什麼是jwt。

什麼是jwt

在介紹iris怎麼處理jwt之前先說明一下jwt是什麼,jwt就是JSON Web Token的縮寫,詳細內容可以看一下jwt wiki的說明,簡單來說就是一種驗證使用者的協定,這協定可以將使用者的資料加密存放在token之中,因此可以透過這token來取得使用者資料而不需要再與資料庫溝通,所以可以再登入最後將些非敏感的使用者資料存放在token之中,所以接下來再跟大家分享一下如何在iris使用jwt。

iris上如何使用jwt

因為iris有內建一個middleware來處理jwt,所以我們藉由iris jwt example這個範例來說明一下在iris如何使用jwt這個middleware來處理JSON Web Token,首先先看一下下列例子

package main

import (
	"github.com/kataras/iris/v12"
	"github.com/iris-contrib/middleware/jwt"
)

var mySecret = []byte("My Secret")

// generate token to use.
func getTokenHandler(ctx iris.Context) {
	token := jwt.NewTokenWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"foo": "bar",
	})

	// Sign and get the complete encoded token as a string using the secret
	tokenString, _ := token.SignedString(mySecret)

	ctx.HTML(`Token: ` + tokenString + `<br/><br/>
<a href="/secured?token=` + tokenString + `">/secured?token=` + tokenString + `</a>`)
}

func myAuthenticatedHandler(ctx iris.Context) {
	user := ctx.Values().Get("jwt").(*jwt.Token)

	ctx.Writef("This is an authenticated request\n")
	ctx.Writef("Claim content:\n")

	foobar := user.Claims.(jwt.MapClaims)
	for key, value := range foobar {
		ctx.Writef("%s = %s", key, value)
	}
}

func main() {
	app := iris.New()

	j := jwt.New(jwt.Config{
		ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
			return mySecret, nil
		},

		// Extract by the "token" url.
		// There are plenty of options.
		// The default jwt's behavior to extract a token value is by
		// the `Authorization: Bearer $TOKEN` header.
		Extractor: jwt.FromParameter("token"),
		// When set, the middleware verifies that tokens are
		// signed with the specific signing algorithm
		// If the signing method is not constant the `jwt.Config.ValidationKeyGetter` callback
		// can be used to implement additional checks
		// Important to avoid security issues described here:
		// https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
		SigningMethod: jwt.SigningMethodHS256,
	})

	app.Get("/", getTokenHandler)
	app.Get("/secured", j.Serve, myAuthenticatedHandler)

	// j.CheckJWT(Context) error can be also used inside handlers.

	app.Listen(":8080")
}

這裡要關注的是getTokenHandler與myAuthenticatedHandler這兩個handler
,接下來我們分段說明jwt的用法。

生成jwt

生成jwt的方法在getTokenHandler可以看到,在這個步驟我們多放一個map到token待之後的範例會介紹如何取出來,最後為了安全措施我們又針對token再加密一次,利用我們的mySecret屬性,完整的語法是tokenString, _ := token.SignedString(mySecret)

驗證jwt

讀者們應該有注意到在綁定myAuthenticatedHandler這handler前有加了另外一個j.Serve如此可以再執行處理請求前先驗證jwt是否合法,所以只要把要加入驗證的handler多加一個j.Serve的前置處理即可。

由jwt中取得使用者資訊

前面有提到可以把使用者資訊存在token中,那要如何取出來呢,這個解答在myAuthenticatedHandler中就可以看得到,簡單講就是透過user := ctx.Values().Get("jwt").(*jwt.Token)就可以取得我們放到token的資訊。
最後可以透過foobar := user.Claims.(jwt.MapClaims)可以取得我們生成token時放進去的資料。

請求時jwt放哪裡

在本例子中是將token放在query string裡面,但是常用的方法是jwt放在header內,如此可以減少被篡改的機會,那樣要如何實作呢,簡單的講就是將Extractor的值改成jwt.FromAuthHeader即可,不過要注意放在header時要記得在token前加上bearer以及一個空格,不然會驗證失敗喔。

會逾期的jwt

上面的例子產生的例子是永久生效的,不過我們可以使用jwt產生使用期限,請大家看一下下面的例子

token := jwt.NewTokenWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
             "foo": "bar",
             "exp": time.Now().Add(time.Hour * time.Duration(12)).Unix() // 合法的時間戳
             "iat": time.Now().Unix() // 簽發token的時間戳

	})

上面的例子將token加上簽發時間戳以及合法的時間戳,最後在生成middleware的config加上以下參數即可


	j := jwt.New(jwt.Config{
            ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
			return mySecret, nil
		},
            Extractor: jwt.FromParameter("token"),
            SigningMethod: jwt.SigningMethodHS256,
            Expiration:true,
	})

結論

本篇跟大家介紹一個驗證的利器jwt,並且介紹如何在iris使用jwt這個middleware,希望能夠幫助大家瞭解關於iris上的使用者驗證的方法。


上一篇
iris的middleware
下一篇
iris的依賴注入
系列文
Iris這個在go語言上地表最快的網頁框架30

尚未有邦友留言

立即登入留言