最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

golang原生實(shí)現(xiàn)JWT的示例代碼

 更新時(shí)間:2023年05月05日 11:23:47   作者:coderDreams  
在Go中實(shí)現(xiàn)JWT驗(yàn)證,可以通過(guò)標(biāo)準(zhǔn)庫(kù)crypto/hmac、crypto/sha256和encoding/base64來(lái)編寫(xiě)自己的JWT,本文就詳細(xì)的來(lái)介紹一下,感興趣的可以了解下

JWT(JSON Web Token)是一種基于JSON的安全令牌,可以用于在不同系統(tǒng)之間傳輸認(rèn)證信息。在Go中實(shí)現(xiàn)JWT驗(yàn)證,可以通過(guò)標(biāo)準(zhǔn)庫(kù)crypto/hmac、crypto/sha256encoding/base64來(lái)編寫(xiě)自己的JWT。

獲取Token

我們?cè)诖朔庋b一個(gè)JWT的struct結(jié)構(gòu)體(由于除了Payload,其他很大可能不會(huì)在其他地方用到,所以不公開(kāi))

type JWT struct {
    header    string
    Payload   string
    signature string
}

將base64的編碼封裝一下方便使用

func encodeBase64(data string) string {
	return base64.RawURLEncoding.EncodeToString([]byte(data))
}

我們封裝一個(gè)用來(lái)生成簽名的方法

func generateSignature(key []byte, data []byte) (string, error) {
	// 創(chuàng)建一個(gè)哈希對(duì)象
	hash := hmac.New(sha256.New, key)
	// 將要簽名的信息寫(xiě)入哈希對(duì)象中 hash.Write(data)
	_, err := hash.Write(data)
	if err != nil {
		return "", err
	}
	// hash.Sum()計(jì)算簽名,在這里會(huì)返回簽名內(nèi)容
	// 將簽名經(jīng)過(guò)base64編碼生成字符串形式返回。
	return encodeBase64(string(hash.Sum(nil))), nil
}

我們封裝一個(gè)CreateToken用于生成Token(該方法的參數(shù)key為(生成簽名所使用的密鑰))

func CreateToken(key []byte, payloadData any) (string, error) {
    // 標(biāo)準(zhǔn)頭部
	header := `{"alg":"HS256","typ":"JWT"}`
    // 將負(fù)載的數(shù)據(jù)轉(zhuǎn)換為json
	payload, jsonErr := json.Marshal(payloadData)
	if jsonErr != nil {
		return "", fmt.Errorf("負(fù)載json解析錯(cuò)誤")
	}
    // 將頭部和負(fù)載通過(guò)base64編碼,并使用.作為分隔進(jìn)行連接
	encodedHeader := encodeBase64(header)
	encodedPayload := encodeBase64(string(payload))
	HeaderAndPayload := encodedHeader + "." + encodedPayload
    // 使用簽名使用的key將傳入的頭部和負(fù)載連接所得的數(shù)據(jù)進(jìn)行簽名
	signature, err := generateSignature(key, []byte(HeaderAndPayload))
	if err != nil {
		return "", err
	}
    // 將token的三個(gè)部分使用.進(jìn)行連接并返回
	return HeaderAndPayload + "." + signature, nil
}

解析Token

我們封裝一個(gè)解析token的方法

func ParseJwt(token string, key []byte) (*JWT, error) {
    // 分解規(guī)定,我們使用.進(jìn)行分隔,所以我們通過(guò).進(jìn)行分隔成三個(gè)字符串的數(shù)組
	jwtParts := strings.Split(token, ".")
    // 數(shù)據(jù)數(shù)組長(zhǎng)度不是3就說(shuō)明token在格式上就不合法
	if len(jwtParts) != 3 {
		return nil, fmt.Errorf("非法token")
	}
	// 分別拿出
	encodedHeader := jwtParts[0]
	encodedPayload := jwtParts[1]
	signature := jwtParts[2]
	// 使用key將token中的頭部和負(fù)載用.連接后進(jìn)行簽名
    // 這個(gè)簽名應(yīng)該個(gè)token中第三部分的簽名一致
	confirmSignature, err := generateSignature(key, []byte(encodedHeader+"."+encodedPayload))
	if err != nil {
		return nil, fmt.Errorf("生成簽名錯(cuò)誤")
	}
    // 如果不一致
	if signature != confirmSignature {
		return nil, fmt.Errorf("token驗(yàn)證失敗")
	}
	// 將payload解base64編碼
	dstPayload, _ := base64.RawURLEncoding.DecodeString(encodedPayload)
    // 返回我們的JWT對(duì)象以供后續(xù)使用
	return &JWT{encodedHeader, string(dstPayload), signature}, nil
}

實(shí)際使用

我們構(gòu)造一個(gè)用戶的結(jié)構(gòu)體

type UserInfo struct {
	Name     string `json:"name"`
	Password string `json:"password"`
}

我們這次使用123456作為密鑰簡(jiǎn)單的驗(yàn)證一下

var Key []byte = []byte("12346")

在此我們構(gòu)造一個(gè)驗(yàn)證的中間件

func jwtConfirm(context *gin.Context) {
	// 登錄不需要token
	if context.Request.RequestURI == "/login" {
		return
	}
	// 拿出token
	token := context.GetHeader("Token")
    // 進(jìn)行解析驗(yàn)證
	jwt, err := utils.ParseJwt(token, Key)
	if err != nil {
		context.JSON(200, gin.H{
			"msg": err.Error(),
		})
        // 有問(wèn)題就流產(chǎn)掉(我也不知道怎么翻譯好了,香蕉貓.jpg)
		context.Abort()
	}
    // 驗(yàn)證通過(guò)就將負(fù)載返回回去
	context.JSON(200, gin.H{
		"payload": jwt.Payload,
	})
}

我們?cè)诖嘶A(chǔ)上就可以使用了,這邊使用gin框架簡(jiǎn)單的測(cè)試一下

func main() {
    // 使用默認(rèn)路由
	router := gin.Default()
    // 注冊(cè)中間件
	router.Use(jwtConfirm)
    // 簡(jiǎn)單做兩個(gè)服務(wù)
	router.POST("/login", func(context *gin.Context) {
		// 接收用戶參數(shù)
		var userInfo UserInfo = UserInfo{}
        // 使用jsonbind接收
		bindErr := context.ShouldBindJSON(&userInfo)
		if bindErr != nil {
			context.JSON(200, gin.H{
				"msg": bindErr.Error(),
			})
		}
		// 使用密鑰做出token
		jwt, err := utils.CreateJwt(Key, userInfo)
		if err != nil {
			fmt.Println(err)
		}
         // 我們將token直接返回用于測(cè)試
		context.JSON(200, gin.H{
			"token": jwt,
		})
	})
	router.GET("/doing")
	router.Run()
}

測(cè)試結(jié)果

image-20230429184039413.png

我們拿到了token

我們現(xiàn)在去試一下如果不帶token的結(jié)果

image-20230429184135724.png

我們?cè)囈幌聰y帶錯(cuò)誤token的情況

image-20230429184233619.png

我們最后測(cè)試一下正確的token

image-20230429184635149.png

結(jié)語(yǔ)

在實(shí)際環(huán)境中會(huì)使用更復(fù)雜的情況進(jìn)行使用(例如密鑰會(huì)更加復(fù)雜,會(huì)在pyload中設(shè)置失效時(shí)間等等),但是生成token和解析token的操作和上述的操作差別不大

到此這篇關(guān)于golang原生實(shí)現(xiàn)JWT的示例代碼的文章就介紹到這了,更多相關(guān)golang原生實(shí)現(xiàn)JWT內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang函數(shù)這些神操作你知道哪些

    Golang函數(shù)這些神操作你知道哪些

    這篇文章主要為大家介紹了一些Golang中函數(shù)的神操作,不知道你都知道哪些呢?文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,需要的可以參考一下
    2023-02-02
  • Go語(yǔ)言開(kāi)發(fā)環(huán)境搭建與初探(Windows平臺(tái)下)

    Go語(yǔ)言開(kāi)發(fā)環(huán)境搭建與初探(Windows平臺(tái)下)

    Go是Google開(kāi)發(fā)的一種編譯型,並發(fā)型,并具有垃圾回收功能的編程語(yǔ)言,可能很多人想學(xué)習(xí)go語(yǔ)言,那么首先就要了解go語(yǔ)言的環(huán)境配置方法
    2014-10-10
  • 淺談Golang的方法傳遞值應(yīng)該注意的地方

    淺談Golang的方法傳遞值應(yīng)該注意的地方

    這篇文章主要介紹了淺談Golang的方法傳遞值應(yīng)該注意的地方,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • Go?結(jié)構(gòu)體序列化的實(shí)現(xiàn)

    Go?結(jié)構(gòu)體序列化的實(shí)現(xiàn)

    本文主要介紹了Go?結(jié)構(gòu)體序列化的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • goframe重寫(xiě)FastAdmin后端實(shí)現(xiàn)實(shí)例詳解

    goframe重寫(xiě)FastAdmin后端實(shí)現(xiàn)實(shí)例詳解

    這篇文章主要為大家介紹了goframe重寫(xiě)FastAdmin后端實(shí)現(xiàn)實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • 最新評(píng)論

    延长县| 利津县| 洪江市| 新沂市| 镇沅| 循化| 都匀市| 晴隆县| 平昌县| 南投市| 英吉沙县| 贵德县| 延川县| 旬阳县| 咸丰县| 多伦县| 祥云县| 准格尔旗| 安多县| 长春市| 大方县| 晋中市| 南充市| 新晃| 通江县| 涞源县| 虹口区| 湖南省| 镇坪县| 邢台市| 孙吴县| 通江县| 叙永县| 西昌市| 榆中县| 离岛区| 尼勒克县| 怀仁县| 朝阳区| 甘南县| 阿尔山市|