You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Go中通过HTTP实现RPC服务端与客户端认证?附示例

Go RPC 基于HTTP基础认证的实现示例

服务端实现(带Basic Auth校验)

在原有HTTP RPC服务外层添加认证中间件,拦截请求并校验客户端的基础认证信息:

package main

import (
	"encoding/base64"
	"fmt"
	"net/http"
	"net/rpc"
	"strings"
)

// RPC服务定义,沿用示例中的算术服务
type Arith int

func (t *Arith) Multiply(args *struct{A, B int}, reply *int) error {
	*reply = args.A * args.B
	return nil
}

// BasicAuthMiddleware 基础认证中间件
func BasicAuthMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		authHeader := r.Header.Get("Authorization")
		if authHeader == "" {
			w.Header().Set("WWW-Authenticate", `Basic realm="RPC Service"`)
			http.Error(w, "认证失败", http.StatusUnauthorized)
			return
		}

		// 解析Basic Auth格式的请求头
		parts := strings.SplitN(authHeader, " ", 2)
		if len(parts) != 2 || parts[0] != "Basic" {
			http.Error(w, "无效的认证格式", http.StatusUnauthorized)
			return
		}

		decoded, err := base64.StdEncoding.DecodeString(parts[1])
		if err != nil {
			http.Error(w, "认证信息解码失败", http.StatusUnauthorized)
			return
		}

		// 校验用户名和密码
		credentials := strings.SplitN(string(decoded), ":", 2)
		if len(credentials) != 2 || credentials[0] != "demo_user" || credentials[1] != "demo_pass" {
			http.Error(w, "用户名或密码错误", http.StatusUnauthorized)
			return
		}

		// 认证通过,转发请求到RPC处理逻辑
		next.ServeHTTP(w, r)
	})
}

func main() {
	arith := new(Arith)
	rpc.Register(arith)
	rpc.HandleHTTP()

	// 用认证中间件包裹RPC的HTTP处理器
	http.Handle("/rpc", BasicAuthMiddleware(http.DefaultServeMux))

	fmt.Println("RPC服务启动,监听8080端口")
	if err := http.ListenAndServe(":8080", nil); err != nil {
		fmt.Printf("服务启动失败: %v\n", err)
	}
}

客户端实现(携带Basic Auth请求)

客户端在发起RPC请求时,通过HTTP请求头携带基础认证信息,这里用自定义HTTP请求的方式实现:

package main

import (
	"encoding/base64"
	"fmt"
	"net/http"
	"net/rpc"
)

func main() {
	// 构造Basic Auth认证字符串
	username := "demo_user"
	password := "demo_pass"
	authStr := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password)))

	// 创建HTTP请求并添加认证头
	req, err := http.NewRequest("POST", "http://localhost:8080/rpc", nil)
	if err != nil {
		fmt.Printf("创建请求失败: %v\n", err)
		return
	}
	req.Header.Set("Authorization", "Basic "+authStr)

	// 发起请求并基于响应创建RPC客户端
	httpClient := &http.Client{}
	resp, err := httpClient.Do(req)
	if err != nil {
		fmt.Printf("发起请求失败: %v\n", err)
		return
	}
	defer resp.Body.Close()

	rpcClient, err := rpc.NewClient(resp.Body)
	if err != nil {
		fmt.Printf("创建RPC客户端失败: %v\n", err)
		return
	}
	defer rpcClient.Close()

	// 调用RPC乘法方法
	var reply int
	args := struct{A, B int}{A: 4, B: 6}
	err = rpcClient.Call("Arith.Multiply", args, &reply)
	if err != nil {
		fmt.Printf("RPC调用失败: %v\n", err)
		return
	}
	fmt.Printf("4 * 6 = %d\n", reply)
}

核心说明

  • 服务端中间件会优先拦截所有/rpc路径的请求,完成认证校验后才会放行到RPC处理逻辑,未通过认证的请求会直接返回401状态码。
  • 客户端通过在HTTP请求头中添加Authorization: Basic <base64编码的用户名:密码>字段完成认证,确保请求能通过服务端校验。
  • 实际使用时可将硬编码的用户名密码改为从配置文件读取,或接入数据库等存储方式动态校验。

内容的提问来源于stack exchange,提问作者清晨的雾

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 22:05:43