更新於 2024/05/20閱讀時間約 9 分鐘

[Go]OAuth2.0

授權碼模式連線流程

  1. 用戶端請求自己的伺服器。
  2. 伺服器發現用戶沒登入,就導向認證伺服器。
  3. 認證伺服器顯示授權頁面,等待用戶授權。
  4. 用戶確認授權後,授權頁面會向認證伺服器請求授權碼。
  5. 用戶獲取授權碼。
  6. 用戶將授權碼傳給伺服器。
  7. 伺服器拿授權碼向認證伺服器取得token。


應用註冊

到第三方網站進行登記,讓第三方知道是誰在請求。


HTML

登入

<!DOCTYPE HTML>
<html>
<body>
<a href="OAuth_URL?client_id=your_client_id&redirect_uri=your_redirect_uri">
Login by OAuth_URL
</a>
</body>
</html>


登入成功

<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, INItial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello</title>
</head>
<body>
</body>
<script>
//取得url參數
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
return (false);
}
//獲取access_token
const token = getQueryVariable("access_token");
//呼叫用戶資訊介面
fetch('OAuth_URL_api', {
headers: {
Authorization: 'token ' + token
}
})
//解析請求的JSON
.then(res => res.json())
.then(res => {
//返回用戶資訊
const nameNode = document.createTextNode(`Hi, ${res.name}, Welcome to login our site by OAuth!`)
document.body.appendChild(nameNode)
})
</script>
</html>


Go

package main

import (
"encoding/json"
"fmt"
"html/template"
"net/http"
"os"
)

const clientID = "your_client_id"
const clientSecret = "your_client_secret"

func hello(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
t, _ := template.ParseFiles("your_login_suceesfully_html")
t.Execute(w, nil)
}
}

func login(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
t, _ := template.ParseFiles("your_login_html")
t.Execute(w, nil)
}
}

func main() {
http.HandleFunc("/your_login", your_login)
http.HandleFunc("/", your_login_suceesfully)
http.HandleFunc("/your_login_suceesfully", your_login_suceesfully)

httpClient := http.Client{}
http.HandleFunc("/oauth/redirect", func(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm()
if err != nil {
fmt.Fprintf(os.Stdout, "could not parse query: %v", err)
w.WriteHeader(http.StatusBadRequest)
}
code := r.FormValue("code")

reqURL := fmt.Sprintf("your_OAuth_access_token?" +
"client_id=%s&client_secret=%s&code=%s", clientID, clientSecret, code)
req, err := http.NewRequest(http.MethodPost, reqURL, nil)
if err != nil {
fmt.Fprintf(os.Stdout, "could not create HTTP request: %v", err)
w.WriteHeader(http.StatusBadRequest)
}
req.Header.Set("accept", "application/json")

res, err := httpClient.Do(req)
if err != nil {
fmt.Fprintf(os.Stdout, "could not send HTTP request: %v", err)
w.WriteHeader(http.StatusInternalServerError)
}
defer res.Body.Close()

var t AccessTokenResponse
if err := json.NewDecoder(res.Body).Decode(&t); err != nil {
fmt.Fprintf(os.Stdout, "could not parse JSON response: %v", err)
w.WriteHeader(http.StatusBadRequest)
}

w.Header().Set("Location", "/your_login_suceesfully_html?access_token="+t.AccessToken)
w.WriteHeader(http.StatusFound)
})

http.ListenAndServe(":8087", nil)
}

type AccessTokenResponse struct {
AccessToken string `json:"access_token"`
}

code為用來取得access_token的授權碼。







分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.