编写代码
admin@hpc-1:~/go$ mkdir auth_http
admin@hpc-1:~/go$ cd auth_http
admin@hpc-1:~/go/auth_http$
admin@hpc-1:~/go/auth_http$ go mod init my_auth
go: creating new go.mod: module my_auth
admin@hpc-1:~/go/auth_http$
admin@hpc-1:~/go/auth_http$ cat go.mod
module my_auth
go 1.18
admin@hpc-1:~/go/auth_http$
admin@hpc-1:~/go/auth_http$ tree
.
├── go.mod
├── http_rpc_server.go
└── utils
└── do_auth.go
1 directory, 3 files
admin@hpc-1:~/go/auth_http$
admin@hpc-1:~/go/auth_http$ cat http_rpc_server.go
package main
import (
"fmt"
"log"
"flag"
"net/http"
"encoding/json"
"my_auth/utils"
)
// 定义一个用于接收请求的结构体
type MapPrinter struct{}
// 定义一个用于接收请求的方法
func (m *MapPrinter) PrintMap(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// 检查认证头部信息
username, password, ok := r.BasicAuth()
if !ok {
// 未提供基本身份验证,返回 401 Unauthorized
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprintln(w, "401 Unauthorized")
return
}
// 验证用户名和密码
if !utils.CheckCredentials(username, password) {
// 用户名和密码不匹配,返回 401 Unauthorized
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprintln(w, "401 Unauthorized")
return
}
var payload map[string]interface{}
err := json.NewDecoder(r.Body).Decode(&payload)
if err != nil {
http.Error(w, "Invalid payload", http.StatusBadRequest)
return
}
fmt.Println("Received payload:")
for key, value := range payload {
fmt.Printf("%s: %v\n", key, value)
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("Map printed successfully\n"))
}
func main() {
//获取监听端口,默认8080
port := flag.String("p", "8080", "指定监听端口")
// 解析命令行参数
flag.Parse()
//注册abc-api路由
http.HandleFunc("/abc-api", new(MapPrinter).PrintMap)
admin@hpc-1:~/go/auth_http$
admin@hpc-1:~/go/auth_http$
admin@hpc-1:~/go/auth_http$
admin@hpc-1:~/go/auth_http$ cat utils/do_auth.go
package utils
func CheckCredentials(username, password string) bool {
validUsername := "admin"
validPassword := "admin"
return username == validUsername && password == validPassword
}
admin@hpc-1:~/go/auth_http$
一些说明
go mode init <package_name>
是将代码从GOPATH 模式迁移到模块模式。然后使用模块路径来导入其他模块或包- golang的项目必须要有
- 至少一个go文件以
package main
开头 - 有且仅有一个go文件包含
func main()
作为程序执行的入口
utils
目录下的所有文件(本例中只有do_auth.go一个文件)都以package utils
开头,表明这些文件都属于utils
这个自定义包的组成部分- 注意,utils中的函数如何要被外部函数调用,必须
以大写字母开头
,例如本例中的CheckCredentials - 当要调用
utils
中的函数的时候
import "my_auth/utils"
,就是由init时候创建的模块加上"/",再加上自定义的package name- 调用
utils
里面的函数的时候,使用utils.Xxxxx来调用,此时和那个函数具体写在哪个文件中就没有关系了(本例中调用时候就不会出现do_auth这个文件名)
运行
admin@hpc-1:~/go/auth_http$ go build -o http_rpc_server
admin@hpc-1:~/go/auth_http$
admin@hpc-1:~/go/auth_http$ file http_rpc_server
http_rpc_server: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, Go BuildID=jj_W4SsJdLxNOWHH706-/p8kU3nvIDJ1cRjEIGWFi/752lBQWnErUy3P6gdHgN/2ksEePP3sNj-He57uoCu, not stripped
admin@hpc-1:~/go/auth_http$
admin@hpc-1:~/go/auth_http$ chmod +x http_rpc_server
admin@hpc-1:~/go/auth_http$
admin@hpc-1:~/go/auth_http$ ./http_rpc_server -p 8090
Server is listening on port %s... 8090
验证
不指定auth header
- 另开终端,用curl发送POST请求,不带username-password
admin@hpc-1:~/go/auth_http$ curl -X POST -H "Content-Type: application/json" -d '{"key1":"value1", "key2":"value2"}' http://localhost:8090/abc-api
401 Unauthorized
admin@hpc-1:~/go/auth_http$
auth header与期望的不匹配
- 代码中期望用户名和密码为admin/admin,故意不匹配
admin@hpc-1:~/go/auth_http$ curl -X POST -u admin:password -H "Content-Type: application/json" -d '{"key1":"value1", "key2":"value2"}' http://localhost:8090/abc-api
401 Unauthorized
admin@hpc-1:~/go/auth_http$
auth header与期望的匹配
admin@hpc-1:~/go/auth_http$ curl -X POST -u admin:admin -H "Content-Type: application/json" -d '{"key1":"value1", "key2":"value2"}' http://localhost:8090/abc-api
Map printed successfully
admin@hpc-1:~/go
admin@hpc-1:~/go/auth_http$ ./http_rpc_server -p 8090
Server is listening on port %s... 8090
Received payload:
key1: value1
key2: value2