Go語言實現GitHub第三方登入(基於Gin框架實現)

語言: CN / TW / HK

highlight: atelier-dune-light theme: orange


前言

在我們製作網站或者製作APP的時候,經常就會想到去實現一個第三方登入,因為GitHub的相關介面已經非常完善,所以這次用GitHub進行演示

OAuth2.0

OAuth2.0是什麼

說到第三方登入,那不得不談的就是OAuth2.0。OAuth2.0是OAuth協議的延續版本,但不向前相容OAuth 1.0(即完全廢止了OAuth1.0)。 OAuth 2.0關注客戶端開發者的簡易性。要麼通過組織在資源擁有者和HTTP服務商之間的被批准的互動動作代表使用者,要麼允許第三方應用代表使用者獲得訪問的許可權。同時為Web應用,桌面應用和手機,和起居室裝置提供專門的認證流程。2012年10月,OAuth 2.0協議正式釋出為RFC 6749

OAuth2.0有什麼用

  • 第三方應用登入: 比如利用QQ,微博,微信授權登入到其他網站或App
  • 分散式或微服務專案中授權:JAVA分散式或微服務開發時,後端業務拆分成若干服務,服務之間或前端進行請求呼叫時,為了安全認證,可以利用OAuth2.0進行認證授權。

實現方法

我們需要先在GitHub上進行登記處理,依次按一下操作進行

image-20220313172451550

image-20220313172526740

image-20220313172544797

callback URL最為重要,此地址為重定向回的URL

image-20220313172600886

image-20220313172625131

Client ID和secrets會在後面有幫助

前端頁面

因為博主並不會前端,所以只起了一個非常簡單的頁面,並命為register.html,圖示隨意找一個或者不用都行

html <a href="https://github.com/login/oauth/authorize? client_id=a915******53c297a8ea&redirect_uri=www.*****.work/login/register.html"> <img src="image2/github.jpeg" alt=""></a>

client_id為上文中所獲得的,url需要和GitHub中輸入的保持一致

image-20220313173756982

後端實現

model層

```go type Conf struct { ClientId string ClientSecret string //GitHub裡所獲取 RedirectUrl string //重定向URL }

type Token struct { AccessToken string json:"access_token" //唯一有用,所以只傳了這個 } ```

service層

```go var conf = model.Conf{ ClientId: "a91**c53c297a8ea", ClientSecret: "d39c4*b4d493b17745ac2db24f699be08f", RedirectUrl: "http://42.192..29:8080/oauth", }

//獲取地址 func GetTokenAuthUrl(code string) string { return fmt.Sprintf( "https://github.com/login/oauth/access_token?client_id=%s&client_secret=%s&code=%s", conf.ClientId, conf.ClientSecret, code, ) }

func GetToken(url string) (*model.Token, error) {

// 形成請求 var req *http.Request var err error if req, err = http.NewRequest(http.MethodGet, url, nil); err != nil { return nil, err } req.Header.Set("accept", "application/json")

// 傳送請求並獲得響應 var httpClient = http.Client{} var res *http.Response if res, err = httpClient.Do(req); err != nil { return nil, err }

// 將響應體解析為 token,並返回 var token model.Token if err = json.NewDecoder(res.Body).Decode(&token); err != nil { return nil, err } return &token, nil }

func GetUserInfo(token *model.Token) (map[string]interface{}, error) {

// 形成請求 var userInfoUrl = "https://api.github.com/user" // github使用者資訊獲取介面 var req *http.Request var err error if req, err = http.NewRequest(http.MethodGet, userInfoUrl, nil); err != nil { return nil, err } req.Header.Set("accept", "application/json") req.Header.Set("Authorization", fmt.Sprintf("token %s", token.AccessToken))

// 傳送請求並獲取響應 var client = http.Client{} var res *http.Response if res, err = client.Do(req); err != nil { return nil, err } // 將響應的資料寫入 userInfo 中,並返回 var userInfo = make(map[string]interface{}) if err = json.NewDecoder(res.Body).Decode(&userInfo); err != nil { return nil, err } return userInfo, nil } ```

api層

```go func Oauth(ctx gin.Context) { var err error // 獲取 code var code = ctx.Query("code") // 通過 code, 獲取 token var tokenAuthUrl = service.GetTokenAuthUrl(code) var token model.Token if token, err = service.GetToken(tokenAuthUrl); err != nil { tool.RespInternalError(ctx) return } ​ // 通過token,獲取使用者資訊 var userInfo map[string]interface{} userInfo, err = service.GetUserInfo(token) if err != nil { tool.RespInternalError(ctx) return } user := userInfo["login"].(string)//獲取GitHub使用者的註冊名便於註冊 c := model.MyClaims{ Username: user, StandardClaims: jwt.StandardClaims{ NotBefore: time.Now().Unix() - 60, ExpiresAt: time.Now().Unix() + 6000000, Issuer: "xx", }, } t := jwt.NewWithClaims(jwt.SigningMethodHS256, c) s, err := t.SignedString(mySigningKey) if err != nil { tool.RespInternalError(ctx) } tool.RespSuccessfulWithTwoDate2(ctx, user, s)//向前端傳出token以及使用者名稱

} ```

最後將其註冊在你的路由中即可

效果

由於沒有前端,只能看看網頁呈現的JSON格式資源

image-20220313193624273

完整專案地址https://github.com/RedRock-Vacation-Assessment-Douban/Douban

結語

如果有沒弄清楚的地方歡迎大家向我提問,我都會盡力解答

這是我的GitHub主頁 github.com/L2ncE

歡迎大家Follow/Star/Fork三連