国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

gin框架39--重構(gòu) BasicAuth 中間件

這篇具有很好參考價值的文章主要介紹了gin框架39--重構(gòu) BasicAuth 中間件。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

介紹

每當(dāng)我們打開一個網(wǎng)址的時候,會自動彈出一個認(rèn)證界面,要求我們輸入用戶名和密碼,這種BasicAuth是最基礎(chǔ)、最常見的認(rèn)證方式,gin框架中提供了一種內(nèi)置的方式,但它只能用內(nèi)置的用戶和密碼,無法使用外部db中的用戶和密碼,這種方式很多時候是不友好的。
為此,本文根據(jù)gin.BasicAuth的原理對其就行重構(gòu),實(shí)現(xiàn)一個簡單的newAuth中間件,該中間件可以代替默認(rèn)的BasicAuth,并且可以按需更改為自定義查詢函數(shù),實(shí)現(xiàn)從外部db或者用戶管理系統(tǒng)查詢信息實(shí)現(xiàn)登錄認(rèn)證的功能。

gin BasicAuth 解析

博文 gin框架14–使用 BasicAuth 中間件 介紹了BasicAuth 中間件的基礎(chǔ)使用方法,直接使用 gin.BasicAuth(gin.Accounts{“foo”: “bar”, “austin”: “1234”, “l(fā)ena”: “hello2”, “manu”: “4321”, }) 即可,非常簡單實(shí)用。

實(shí)際上當(dāng)我們訪問url的時候,它會從請求的 Authorization 中獲取用戶信息,并和gin.Accounts中內(nèi)置用戶對比,如果用戶存在就將用戶名稱存放在Context的 Keys map結(jié)構(gòu)中,方便后續(xù)查找或者獲取用戶信息;如果不存在就設(shè)置c.Header(“WWW-Authenticate”, realm), 并返回c.AbortWithStatus(http.StatusUnauthorized),瀏覽器上的表現(xiàn)就是重新彈出輸入用戶名和密碼的窗口 。

核心邏輯在 BasicAuthForRealm 方法中,如下所示:

func BasicAuthForRealm(accounts Accounts, realm string) HandlerFunc {
	if realm == "" {
		realm = "Authorization Required"
	}
	realm = "Basic realm=" + strconv.Quote(realm)
	pairs := processAccounts(accounts)
	return func(c *Context) {
		// Search user in the slice of allowed credentials
		user, found := pairs.searchCredential(c.requestHeader("Authorization"))
		if !found {
			// Credentials doesn't match, we return 401 and abort handlers chain.
			c.Header("WWW-Authenticate", realm)
			c.AbortWithStatus(http.StatusUnauthorized)
			return
		}

		// The user credentials was found, set user's id to key AuthUserKey in this context, the user's id can be read later using
		// c.MustGet(gin.AuthUserKey).
		c.Set(AuthUserKey, user)
	}
}

自定義newAuth實(shí)現(xiàn)基礎(chǔ)認(rèn)證

gin.BasicAuth 只能提供默認(rèn)的認(rèn)證功能,且需要內(nèi)置指定的用戶|密碼,但實(shí)際在代碼中hardcode大量用戶信息是不科學(xué)的,因此我們需要自己重構(gòu)一個BasicAuth來實(shí)驗(yàn)基礎(chǔ)認(rèn)證功能。
此處實(shí)現(xiàn)了一個newAuth中間件,該中間件會判斷用戶是否輸入賬號|密碼,并通過judgeUserExist來判斷賬號|密碼是否正確,正確則返回用戶信息,不正確則返回http.StatusUnauthorized, 具體案例如下。

此處為了簡潔方便,此處直接內(nèi)置了3個用戶到users中,并用 judgeUserExist 查詢用戶賬號密碼是否正確。實(shí)際項(xiàng)目中可將該方法更改為查詢db,無需在項(xiàng)目中hardcode內(nèi)置用戶。

package main

import (
	"encoding/base64"
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"strconv"
	"strings"
)

var users = gin.H{
	"foo":    gin.H{"email": "foo@bar.com", "phone": "123433", "pwd": "bar"},
	"austin": gin.H{"email": "austin@example.com", "phone": "666", "pwd": "123"},
	"lena":   gin.H{"email": "lena@guapa.com", "phone": "523443", "pwd": "456"},
}

func help() string {
	helpStr := `hello gin:
127.0.0.1:8088/your-api
/auth/user
`
	return helpStr
}

func judgeUserExist(userName, userPwd string) (string, bool) {
	// 實(shí)際項(xiàng)目中將該函數(shù)更改為從db查詢即可,此處為了簡單直接從預(yù)定的users中查詢。
	msg := ""
	tag := false
	if userInfo, ok := users[userName]; ok {
		pwd, ok := userInfo.(gin.H)["pwd"]
		if ok && pwd == userPwd {
			msg = fmt.Sprintf("用戶%v密碼正確", userName)
			tag = true
		} else {
			msg = fmt.Sprintf("用戶%v密碼不正確", userName)
		}
	} else {
		msg = fmt.Sprintf("用戶%v不存在", userName)
	}
	return msg, tag
}

func getUserPwdFromAuthorization(auth string) (user, pwd string) {
	// auth[:6]="Basic "
	base64UserPwd, err := base64.StdEncoding.DecodeString(auth[6:])
	if err != nil {
		panic(err)
	}
	base64UserPwdStr := string(base64UserPwd)
	colonIndex := strings.Index(base64UserPwdStr, ":")
	user = base64UserPwdStr[:colonIndex]
	pwd = base64UserPwdStr[colonIndex+1:]
	return user, pwd
}

func newAuth(realm string) func(c *gin.Context) {
	if realm == "" {
		realm = "Authorization Required"
	}
	realm = "Basic realm=" + strconv.Quote(realm)
	return func(c *gin.Context) {
		authHeader := c.Request.Header.Get("Authorization") // 獲取請求頭中的數(shù)據(jù)
		if authHeader == "" {
			c.Header("WWW-Authenticate", realm)
			c.AbortWithStatus(http.StatusUnauthorized)
			return
		} else {
			user, pwd := getUserPwdFromAuthorization(authHeader)
			// fmt.Printf("user=%v,pwd=%v\n", user, pwd)
			msg, tag := judgeUserExist(user, pwd)
			if !tag {
				// c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"msg": msg, "tag": tag})
				fmt.Println(msg)
				c.AbortWithStatus(http.StatusUnauthorized)
				return
			}
			c.Set(gin.AuthUserKey, user)
		}
	}
}

func userHandler(c *gin.Context) {
	user := c.MustGet(gin.AuthUserKey).(string)
	c.IndentedJSON(http.StatusOK, gin.H{
		"status":   200,
		"msg":      "it's fine",
		"userInfo": users[user],
	})
}

func main() {
	app := gin.Default()
	app.GET("/", func(c *gin.Context) {
		c.String(http.StatusOK, help())
	})

	authorized := app.Group("/auth", newAuth(""))
	authorized.GET("/user", userHandler)
	app.Run(":8088")
}

輸出:
gin框架39--重構(gòu) BasicAuth 中間件,Golang,gin,重構(gòu),中間件文章來源地址http://www.zghlxwxcb.cn/news/detail-721457.html

注意事項(xiàng)

  1. c.Header中需要添加 WWW-Authenticate 字段,否則初次訪問的時候不會彈出輸入用戶名、密碼的框!!!

說明

  1. 測試環(huán)境
    ubuntu22.04 Desktop
    go1.20.7
  2. 參考文檔
    using-basicauth-middleware
    Gin框架 -- 中間件

到了這里,關(guān)于gin框架39--重構(gòu) BasicAuth 中間件的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • gin中間件篇

    gin中間件篇

    所有請求都經(jīng)過此中間件 輸出結(jié)果: 輸出結(jié)果: 效果演示: 定義程序計時中間件,然后定義2個路由,執(zhí)行函數(shù)后應(yīng)該打印統(tǒng)計的執(zhí)行時間,如下: 效果演示: 參考文章: https://www.fansimao.com/928855.html? gin Next()方法 - 范斯貓

    2024年01月21日
    瀏覽(25)
  • Go Gin中間件

    Go Gin中間件

    Gin是一個用Go語言編寫的Web框架,它提供了一種簡單的方式來創(chuàng)建HTTP路由和處理HTTP請求。中間件是Gin框架中的一個重要概念,它可以用來處理HTTP請求和響應(yīng),或者在處理請求之前和之后執(zhí)行一些操作。 以下是關(guān)于Gin中間件開發(fā)的一些基本信息: 中間件的定義 :在Gin中,中

    2024年02月05日
    瀏覽(28)
  • GO——gin中間件和路由

    GO——gin中間件和路由

    中間件 參考:https://learnku.com/articles/66234 結(jié)構(gòu) 中間件是函數(shù) 中間件函數(shù)被放在調(diào)用鏈上 調(diào)用鏈的末尾是路由path對應(yīng)的函數(shù) 執(zhí)行過程 net/http包調(diào)用到gin的serverHTTP 參考:go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/gin.go:506 通過path找到路由對應(yīng)的處理鏈,賦值給context 參考:go/pkg/mod/git

    2024年01月17日
    瀏覽(22)
  • gin中使用限流中間件

    gin中使用限流中間件

    限流又稱為流量控制(流控),通常是指限制到達(dá)系統(tǒng)的并發(fā)請求數(shù),本文列舉了常見的限流策略,并以gin框架為例演示了如何為項(xiàng)目添加限流組件。 限流又稱為流量控制(流控),通常是指限制到達(dá)系統(tǒng)的并發(fā)請求數(shù)。 我們生活中也會經(jīng)常遇到限流的場景,比如:某景區(qū)

    2024年01月25日
    瀏覽(14)
  • gin 中間件流程控制:Next()、 Abort()

    gin 中間件流程控制:Next()、 Abort()

    源碼注釋: Next 應(yīng)該只在中間件內(nèi)部使用。它執(zhí)行調(diào)用處理程序內(nèi)部鏈中的掛起處理程序。 通俗的說,就是中間件放行,當(dāng)一個中間件代碼執(zhí)行到 Next() ,會先執(zhí)行它之后的函數(shù),最后再來執(zhí)行完本函數(shù)。 eg: 如果其中一個中間件響應(yīng)了c.Abort(),后續(xù)中間件將不再執(zhí)行,直接按

    2024年02月15日
    瀏覽(36)
  • 簡單記錄下gin中使用中間件記錄操作日志

    1、直接定義中間件 2、在需要使用的地方直接使用就可以,自動會收集日志到數(shù)據(jù)庫中

    2024年02月09日
    瀏覽(19)
  • gin自定義中間件解決requestBody不可重復(fù)讀問題

    gin自定義中間件解決requestBody不可重復(fù)讀問題

    先直接上代碼 注意,上面的中間件,需要在第一個執(zhí)行。 在gin中,context.Request.Body 是一個io.ReadCloser的接口,如下圖 查看io.ReadCloser接口定義 我們發(fā)現(xiàn)io.ReaderCloser接口的本質(zhì)就是 Read(p []byte) (n int, err error) 和 Close() error 的組合。 所以我們只需要自己編寫實(shí)現(xiàn) Read(p []byte) (n in

    2024年02月01日
    瀏覽(18)
  • Gin CORS 跨域請求資源共享與中間件

    Gin CORS 跨域請求資源共享與中間件

    1.1 什么是瀏覽器的同源策略? 同源策略 (Same origin policy) 是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會受到影響??梢哉fWeb是構(gòu)建在同源策略基礎(chǔ)之上的,瀏覽器只是針對同源策略的一種實(shí)現(xiàn) 瀏覽器最基本的安

    2024年01月25日
    瀏覽(25)
  • Go學(xué)習(xí)第十七章——Gin中間件與路由

    Go學(xué)習(xí)第十七章——Gin中間件與路由

    Gin框架允許開發(fā)者在處理請求的過程中,加入用戶自己的鉤子(Hook)函數(shù)。這個鉤子函數(shù)就叫中間件,中間件適合處理一些公共的業(yè)務(wù)邏輯,比如登錄認(rèn)證、權(quán)限校驗(yàn)、數(shù)據(jù)分頁、記錄日志、耗時統(tǒng)計等 即比如,如果訪問一個網(wǎng)頁的話,不管訪問什么路徑都需要進(jìn)行登錄,

    2024年02月07日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包