Golang 使用 Gin 框架接收 HTTP Post 请求体中的 JSON 数据

本文介绍了在Golang1.21.4版本的Gin框架中,如何使用mapinterface和自定义实体接收JSON数据,以及处理绑定JSON时可能出现的错误。创建TodoItem的方法展示了如何正确解析请求体并返回HTTP响应。
部署运行你感兴趣的模型镜像

Golang 版本为 1.21.4,Gin 版本 1.9.1,记录的接收方法仅针对使用请求体发送的 JSON 数据。

使用 map interface 接收数据

需要注意的是接收之后的 key 的访问需要在常规 map 访问方式之后添加 .({type}),否则出错。

// createTodo 方法添加一条新的数据
func createTodo(c *gin.Context) {
	body := make(map[string]interface{})
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	completed, _ := strconv.Atoi(body["completed"].(string))
	todo := todoModel{Title: body["title"].(string), Completed: completed}
	// ...
	c.JSON(http.StatusCreated, gin.H{"status": http.StatusCreated, "message": "Todo item created successfully!", "resourceId": todo.ID})
}

使用自定义实体接收数据

需要保证 JSON 中发送的类型与实体中定义类型一致,使用 Int 接收 string 类型则会出错。

// createTodo 方法添加一条新的数据
func createTodo(c *gin.Context) {
	var todo todoModel
	if err := c.ShouldBindJSON(&todo); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	// ...
	c.JSON(http.StatusCreated, gin.H{"status": http.StatusCreated, "message": "Todo item created successfully!", "resourceId": todo.ID})
}

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

<think>嗯,用户想用Gin框架POST /hello接口添加Digest认证的代码示例。首先,我得回忆一下Digest认证的基本流程。Digest认证比Basic安全,因为它不直接密码,而是用哈希。步骤大概是客户端请求,服务器返回401带nonce,然后客户端用username、realm、nonce、HTTP方法、URI等生成response,服务器验证对吧?然后,Gin框架中间件的写法。中间件函数需要返回gin.HandlerFunc,里面处理请求。先检查Authorization头是否存在,没有的话返回401,并设置WWW-Authenticate头。这里要注意Realm和nonce的生成,nonce应该随机且有时效性,但示例可能简化处理,直接用固定值或者简单随机数。解析Authorization头的时候,需要按照Digest的格式拆分各个参数,比如username、realm、nonce、uri、response等。可能需要用正则表达式来提取这些键值对。例如,用正则匹配`(\w+)=["']?([^"',]+)`来获取各个部分。 接着,验证部分。需要根据username查找对应的密码,然后计算HA1=MD5(username:realm:password),HA2=MD5(method:uri),然后response=MD5(HA1:nonce:HA2)。然后和客户端来的response比较,如果一致就通过,否则返回401。在代码中,可能需要一个存储用户信息的结构,比如map[string]string来保存用户名和密码。中间件里获取到username后,查找对应的密码,然后进行上述计算。 注意nonce的安全性,实际应用中可能需要更复杂的生成和过期机制,但示例可以简化处理。另外,Realm的值应该和WWW-Authenticate头中的一致。测试的时候,可以用Postman或者curl来发送请求,第一次不带Authorization头,获取到nonce后,第二次带上计算好的Digest信息。需要确保HTTP方法(POST)和URI(/hello)正确,否则response会不匹配。可能遇到的问题:正则表达式是否正确解析Authorization头,特别是如果有逗号或引号的情况;MD5计算的字符串拼接是否正确,比如是否漏掉了冒号或者顺序错误;nonce的管理是否需要服务端存储,示例可能暂时不处理nonce的校验,只做简单的生成。 另外,Gin的中间件应该在路由之前应用,所以代码示例里用r.Use(digestAuthMiddleware)来全局应用,或者可以指定到特定的路由。用户的需求是POST/hello,所以可能更倾向于将该中间件应用到特定的路由上,比如在r.POST("/hello",...)之前使用中间件。不过示例中的中间件是全局的,可能用户需要调整,根据实际情况决定。或者示例为了简洁,采用全局中间件,但实际应用可能需要更细粒度的控制。最后,代码示例需要处理POST请求,所以中间件中获取的HTTP方法应该是POST,但中间件可能需要处理不同方法,所以直接使用c.Request.Method即可,不需要硬编码。综上,整理代码步骤:创建中间件,处理401响应,解析请求头,计算MD5,验证响应值,通过则继续,否则返回401。同时提供测试方法。</think>在Gin框架中实现Digest认证需要以下关键步骤: ### 实现方案 1. **创建认证中间件** ```go func digestAuthMiddleware() gin.HandlerFunc { realm := "Restricted" nonce := "random123" // 生产环境应使用随机值 userDB := map[string]string{"admin": "secret"} return func(c *gin.Context) { authHeader := c.GetHeader("Authorization") // 首次请求返回质询 if authHeader == "" { c.Header("WWW-Authenticate", `Digest realm="`+realm+`", nonce="`+nonce+`"`) c.AbortWithStatusJSON(401, gin.H{"message": "Unauthorized"}) return } // 解析认证头 params := parseAuthHeader(authHeader) if params["username"] == "" || params["response"] == "" { c.AbortWithStatus(400) return } // 验证响应 if validateDigest(c, params, userDB, realm, nonce) { c.Next() } else { c.AbortWithStatus(401) } } } ``` 2. **解析认证头函数** ```go func parseAuthHeader(header string) map[string]string { re := regexp.MustCompile(`(\w+)=["']?([^"',]+)`) matches := re.FindAllStringSubmatch(header, -1) params := make(map[string]string) for _, match := range matches { params[match[1]] = match[2] } return params } ``` 3. **验证逻辑** ```go func validateDigest(c *gin.Context, params map[string]string, users map[string]string, realm, nonce string) bool { username := params["username"] password, exists := users[username] if !exists { return false } ha1 := md5Hash(username + ":" + realm + ":" + password) ha2 := md5Hash(c.Request.Method + ":" + params["uri"]) validResponse := md5Hash(fmt.Sprintf("%s:%s:%s", ha1, nonce, ha2)) return validResponse == params["response"] } func md5Hash(text string) string { return fmt.Sprintf("%x", md5.Sum([]byte(text))) } ``` 4. **路由配置** ```go func main() { r := gin.Default() r.POST("/hello", digestAuthMiddleware(), func(c *gin.Context) { c.JSON(200, gin.H{"message": "Authenticated!"}) }) r.Run(":8080") } ``` ### 测试方法 ```bash # 首次请求获取nonce curl -v -X POST http://localhost:8080/hello # 带认证头的请求 curl -X POST http://localhost:8080/hello \ -H 'Authorization: Digest username="admin", realm="Restricted", nonce="random123", uri="/hello", response="d3f6e5c..."' ``` **注意事项:** 1. 生产环境需要改进nonce生成机制(建议使用时间戳+随机数) 2. 需要实现nonce过期验证 3. 建议使用qop=auth完整性保护[^1] 4. 密码应使用安全存储方案(如bcrypt哈希)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值