golang实现一个BasicAuth的HTTP server

news/2025/2/12 21:53:03/

之前写的《golang实现一个简单的HTTP server》没有包含认证部分
本例给出了支持BasicAuth的实现,以及如何在一个项目中导入自己定义的package

编写代码

  • 创建项目所在文件夹
admin@hpc-1:~/go$ mkdir auth_http
admin@hpc-1:~/go$ cd auth_http
admin@hpc-1:~/go/auth_http$
  • 项目初始化为一个模块,多出了一个go.mod文件
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_authgo 1.18
admin@hpc-1:~/go/auth_http$ 
  • 补齐代码后的目录结构
admin@hpc-1:~/go/auth_http$ tree
.
├── go.mod
├── http_rpc_server.go
└── utils└── do_auth.go1 directory, 3 files
admin@hpc-1:~/go/auth_http$ 
  • 代码内容
admin@hpc-1:~/go/auth_http$ cat http_rpc_server.go 
package mainimport ("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 Unauthorizedw.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)w.WriteHeader(http.StatusUnauthorized)fmt.Fprintln(w, "401 Unauthorized")return}// 验证用户名和密码if !utils.CheckCredentials(username, password) {// 用户名和密码不匹配,返回 401 Unauthorizedw.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() {//获取监听端口,默认8080port := 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 utilsfunc 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
  • 启动server的终端打印
admin@hpc-1:~/go/auth_http$ ./http_rpc_server -p 8090
Server is listening on port %s... 8090
Received payload:
key1: value1
key2: value2

http://www.ppmy.cn/news/1362612.html

相关文章

【selenium】执行 Javascript 脚本 滚动、元素的特殊操作等

某些特殊情况下&#xff0c;使用selenium的api无法操作页面元素&#xff0c;点击、滚动实现的某些功能&#xff0c;可以考虑通过执行js来完成。 为什么不用js写自动化&#xff1f;——selenium第一版是js写的&#xff0c;但js兼容性存在问题&#xff0c;所以引入webdriver 现在…

如何修改docker容器的端口映射

要修改 Docker 容器的端口映射&#xff0c;你需要停止并删除现有的容器&#xff0c;然后使用新的端口映射重新运行容器。以下是详细步骤&#xff1a; 停止容器&#xff1a; 使用 docker stop 命令停止正在运行的容器。替换 <container_id> 为你要停止的容器的 ID 或者容器…

Android中Transition过渡动画的简单使用

前些天发现了一个蛮有意思的人工智能学习网站,8个字形容一下"通俗易懂&#xff0c;风趣幽默"&#xff0c;感觉非常有意思,忍不住分享一下给大家。 &#x1f449;点击跳转到教程 一、布局xml文件代码如下&#xff1a; <?xml version"1.0" encoding&quo…

通俗易懂分析:Vite和Webpack的区别

1、对项目构建的理解 先从浏览器出发&#xff0c; 浏览器是由浏览器内核和JS引擎组成&#xff1b;浏览器内核编译解析html代码和css代码&#xff0c;js引擎编译解析JavaScript代码&#xff1b;所以从本质上&#xff0c;浏览器只能识别运行JavaScript、CSS、HTML代码。 而我们在…

基于Clion+stm32cubemx+rt-thread os进行环境搭建

前言 RT-Thread文档中心Clion开发STM32的环境搭建,请参考之前的文章本次使用的芯片为STM32F407VET6,其他芯片相似.项目创建 使用STM32CubeMx快速生成项目工程,此步骤的话可以参考官方文档 基础配置如下

SpringBoot中Websocket的简单使用

目录 1 Websocket的定义及一些使用场景 2 使用方法 2.1 导入依赖坐标 2.2 创建WebSocket服务 2.3 编写配置类注册WebSocket 2.4 在需要处使用WebSocket服务 1 Websocket的定义及一些使用场景 定义&#xff1a;Websocket实现了浏览器与服务器全双工通信一浏览器和服务器只…

嵌出式003--外部中断

中断&#xff1a;在主程序运行过程中&#xff0c;出现特定的中断触发条件也就是中断源&#xff0c;使得CPU暂停当前正在运行的程序转而去处理中断程序处理完成又返回执行原来被暂停的位置继续执行。 中断优先级&#xff1a;当多个中断源同时申请中断的时候&#xff0c;CPU会根…

家装服务管理:Java技术的创新应用

✍✍计算机毕业编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java、…