MST

星途 面试题库

面试题:Go HTTP客户端处理复杂认证机制

假设需要使用Go的HTTP客户端访问一个要求OAuth 2.0认证的API,简述实现流程并给出关键代码示例。包括如何获取token、在请求头中携带token等操作。
21.8万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 实现流程
    • 获取ClientID和ClientSecret:从API提供方获取用于OAuth 2.0认证的客户端ID和客户端密钥。
    • 构造请求获取Authorization Code:引导用户到授权服务器的授权端点,用户授权后,会返回一个Authorization Code。
    • 使用Authorization Code换取Token:向授权服务器的令牌端点发送请求,带上Authorization Code、ClientID和ClientSecret,获取访问令牌(Access Token)。
    • 使用Token访问API:在后续的HTTP请求头中携带获取到的Access Token来访问需要认证的API。
  2. 关键代码示例
    • 获取Token
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

// TokenResponse 用于解析获取到的Token响应
type TokenResponse struct {
    AccessToken string `json:"access_token"`
    TokenType   string `json:"token_type"`
    ExpiresIn   int    `json:"expires_in"`
}

func getToken() (string, error) {
    clientID := "your_client_id"
    clientSecret := "your_client_secret"
    authorizationCode := "the_authorization_code"
    tokenURL := "https://example.com/oauth2/token"

    data := fmt.Sprintf("grant_type=authorization_code&code=%s&client_id=%s&client_secret=%s", authorizationCode, clientID, clientSecret)
    resp, err := http.Post(tokenURL, "application/x-www-form-urlencoded", bytes.NewBufferString(data))
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return "", err
    }

    var tokenResp TokenResponse
    err = json.Unmarshal(body, &tokenResp)
    if err != nil {
        return "", err
    }

    return tokenResp.AccessToken, nil
}
  • 在请求头中携带Token访问API
func main() {
    token, err := getToken()
    if err != nil {
        fmt.Println("Error getting token:", err)
        return
    }

    apiURL := "https://example.com/api/protected"
    req, err := http.NewRequest("GET", apiURL, nil)
    if err != nil {
        fmt.Println("Error creating request:", err)
        return
    }
    req.Header.Set("Authorization", "Bearer "+token)

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Error making request:", err)
        return
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Error reading response:", err)
        return
    }

    fmt.Println(string(body))
}