当前位置: 首页 > news >正文

golang通过参数控制HTTP server是否使用基本认证

之前写的《golang实现一个BasicAuth的HTTP server》一定会做基本认证。
本例给出了如何通过启动时候指定的参数来控制是否做基本认证

代码对比和解释

  • 给出与上一篇中源码的diff
admin@hpc-1:~/go/auth_http$ diff -ruN http_rpc_server.go_bak http_rpc_server.go
--- http_rpc_server.go_bak      2024-03-21 16:53:58.899582234 +0800
+++ http_rpc_server.go  2024-03-21 17:51:01.878115766 +0800
@@ -11,7 +11,9 @@// 定义一个用于接收请求的结构体
-type MapPrinter struct{}
+type MapPrinter struct{
+    AuthEnabled bool
+}// 定义一个用于接收请求的方法func (m *MapPrinter) PrintMap(w http.ResponseWriter, r *http.Request) {
@@ -19,23 +21,26 @@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
+    // 检查是否启用了基本认证
+    if m.AuthEnabled {
+        // 检查认证头部信息
+        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{}
@@ -57,11 +62,18 @@func main() {//获取监听端口,默认8080port := flag.String("p", "8080", "指定监听端口")
+    //获取是否使能认证,默认不使能
+    authEnabled := flag.Bool("a", false, "Enable basic authentication")// 解析命令行参数flag.Parse()+    // 创建RPC服务实例
+    rpcService := &MapPrinter{
+        AuthEnabled: *authEnabled, // 根据命令行参数设置是否启用基本认证
+    }
+//注册abc-api路由
-    http.HandleFunc("/abc-api", new(MapPrinter).PrintMap)
+    http.HandleFunc("/abc-api", rpcService.PrintMap)fmt.Println("Server is listening on port %s...", *port)log.Fatal(http.ListenAndServe(":" + *port, nil))
admin@hpc-1:~/go/auth_http$ 
  • 解释
    • 定义的结构体MapPrinter增加一个bool属性AuthEnabled ,用来控制是否做基本认证
    • 之前代码中做认证的部分,只有当AuthEnabled为true的时候才执行
    • 通过flag提取-a后面跟着的true或是false用来给AuthEnabled 赋值,默认为false
    • 创建实例rpcService的时候,将flag获取的值赋给AuthEnabled
    • 注册路由的时候,直接关联到实例rpcService
  • 完整源码
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{AuthEnabled bool
}// 定义一个用于接收请求的方法
func (m *MapPrinter) PrintMap(w http.ResponseWriter, r *http.Request) {if r.Method != http.MethodPost {http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)return}// 检查是否启用了基本认证if m.AuthEnabled {// 检查认证头部信息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", "指定监听端口")//获取是否使能认证,默认不使能authEnabled := flag.Bool("a", false, "Enable basic authentication")// 解析命令行参数flag.Parse()// 创建RPC服务实例rpcService := &MapPrinter{AuthEnabled: *authEnabled, // 根据命令行参数设置是否启用基本认证}//注册abc-api路由http.HandleFunc("/abc-api", rpcService.PrintMap)fmt.Println("Server is listening on port %s...", *port)log.Fatal(http.ListenAndServe(":" + *port, nil))
}
admin@hpc-1:~/go/auth_http$ 

验证

不使能认证

  • 运行时候不指定-a,或者 -a=false,注意,不能使用"-a false",否则一直是true!
admin@hpc-1:~/go/auth_http$ ./http_rpc_server -p 8090 -a=false
Server is listening on port %s... 8090
  • 另开终端,无论是不带basic auth header还是随便带什么basic authen header,都可以正常提供服务
admin@hpc-1:~$ curl -X POST  -H "Content-Type: application/json" -d '{"key1":"value1", "key2":"value2"}' http://localhost:8090/abc-api
Map printed successfully
admin@hpc-1:~$ 
admin@hpc-1:~$ 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:~$ 

使能认证

  • 运行时指定-a=true
admin@hpc-1:~/go/auth_http$ ./http_rpc_server -p 8090 -a=true
Server is listening on port %s... 8090
  • 无论是不带基础认证或者是用户名密码不匹配,都会报错
admin@hpc-1:~$ curl -X POST  -H "Content-Type: application/json" -d '{"key1":"value1", "key2":"value2"}' http://localhost:8090/abc-api
401 Unauthorized
admin@hpc-1:~$ 
admin@hpc-1:~$ curl -X POST -u admin:nimda -H "Content-Type: application/json" -d '{"key1":"value1", "key2":"value2"}' http://localhost:8090/abc-api
401 Unauthorized
admin@hpc-1:~$ 
  • 只有带正确的用户名密码认证的请求才会被正确处理
admin@hpc-1:~$ 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:~$ 

额外知识点

  • flag的参数,即可以用空格也可以用=连接flag和赋值(-p=8090 和 -p 8090等价)
  • 只有bool类型是例外,只能是用=
本例中,默认指定authEnabled 为false下面用法表示false
(1)$ ./http_rpc_server -p=8090 -a=false
(2)$ ./http_rpc_server -p=8090 下面用法表示true
(1)$ ./http_rpc_server -p=8090 -a=true
(2)$ ./http_rpc_server -p=8090 -a
(3) ./http_rpc_server -p=8090 -a <随便什么非空格字符,甚至可以是false>
http://www.lryc.cn/news/326487.html

相关文章:

  • javaSwing坦克大战游戏
  • 【面试题】数据底层原理:Elasticsearch写入流程解析
  • 牛客论坛spring initializer选用的构件
  • 【Java程序设计】【C00385】基于(JavaWeb)Springboot的员工信息管理系统(有论文)
  • 【Linux进阶之路】理解UDP,成为TCP。
  • Linux实用操作
  • OpenJudge - 12:加密的病历单
  • QGIS编译(跨平台编译)057:FastCGI编译(Windows、Linux、MacOS环境下编译)
  • jenkins+newman+postman持续集成环境搭建
  • 取消自动设置的开机自启动(pywin32库)请勿仿照!否则可能对电脑造成损害。
  • 金融投贷通(金融投资+贷款通)项目准备
  • 跟我学C++中级篇——STL的中的删除
  • js如何遍历查询一个颗树
  • 【面试必备】针对一个案例,怎么测试
  • vue3 hooks之事件广播(支持跨标签页)
  • go中validate包使用教程
  • canvas画带透明度的直线和涂鸦
  • linux命令 curl忽略https证书
  • 游戏引擎中网络游戏的基础
  • ES6(ECMAScript 6)中常用的知识点总结(包含示例代码)
  • 老师人手必备的教学神器有哪些?这5款教学软件一定要知道!
  • 华为机试题-核酸检测人数
  • SQLAlchemy模型映射提示declarative_base() takes 0 positional arguments but 1 was given
  • linux系统Kubernetes工具ingress暴露服务
  • centos2anolis
  • Cesium安装部署运行
  • 【Android 内存优化】KOOM线程泄漏监控的实现源码分析
  • 【爬虫基础】第1讲 网络爬虫基本知识
  • scrapy爬虫框架
  • 【深度学习】基础知识