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

(Go Gin)Gin学习笔记(五)会话控制与参数验证:Cookie使用、Sessions使用、结构体验证参数、自定义验证参数

1. Cookie介绍

  • HTTP是无状态协议,服务器不能记录浏览器的访问状态,也就是说服务器不能区分两次请求是否由同一个客户端发出
  • Cookie就是解决HTTP协议无状态的方案之一,中文是小甜饼的意思
  • Cookie实际上就是服务器保存在浏览器上的一段信息。浏览器有了Cookie之后,每次向服务器发送请求时都会同时将该信息发送给服务器,服务器收到请求后,就可以根据该信息处理请求
  • Cookie由服务器创建,并发送给浏览器,最终由浏览器保存

1.1 Cookie的用途

  • 测试服务端发送cookie给客户端,客户端请求时携带cookie

1.2 Cookie的使用

  • 测试服务端发送cookie给客户端,客户端请求时携带cookie
package mainimport ("github.com/gin-gonic/gin"
)func main() {r := gin.Default()// 局部中间件r.GET("/demo", func(c *gin.Context) {// 获得内容res, err := c.Cookie("demo")// 如果没有获得cookie,err则会接收到除nil以外的内容;if err != nil {res = "noSet"// 当不存在cookie,则存储c.SetCookie("demo", "弄他", 3600, "", "", false, false)}c.JSON(200, gin.H{"cookie:": res})})r.Run(":8080")
}

SetCookie() 函数内部:

func (c *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool) {if path == "" {path = "/"}http.SetCookie(c.Writer, &http.Cookie{Name:     name,Value:    url.QueryEscape(value),MaxAge:   maxAge,Path:     path,Domain:   domain,SameSite: c.sameSite,Secure:   secure,HttpOnly: httpOnly,})
}
  • name:cookie的键
  • value:cookie的值
  • maxAge:存储cookie最大的时间(seconds)
  • path:cookie详细路径
  • domain:域名
  • secure:是否支持能通过https访问
  • httpOnly:是否允许别人通过js获取自己的cookie

函数内部调用的是http包下的SetCookie()方法

并且,path为空情况下,详细路径默认是根目录

func SetCookie(w ResponseWriter, cookie *Cookie) {if v := cookie.String(); v != "" {w.Header().Add("Set-Cookie", v)}
}

可以看到内部,是在请求头中添加了Set-Cookie属性,为它进行了设置

1.3 小练习

package main import ("github.com/gin-gonic/gin""math/rand""net/http""strconv""time"
)func handler() gin.HandlerFunc {return func(c *gin.Context) {_, err := c.Cookie("token")if err != nil {return}}
}func main() {r := gin.Default()// 设置cookier.GET("/login", func(c *gin.Context) {rand.NewSource(time.Now().UnixNano())cook := strconv.Itoa(rand.Int())c.SetCookie("token", cook, 86400, "/", "localhost", false, true)c.JSON(200, gin.H{"msg": "success"})})// 检查登录r.GET("/home", handler(), func(c *gin.Context) {cookie, err := c.Cookie("token")if err != nil {c.JSON(http.StatusBadRequest, gin.H{"msg": http.StatusBadRequest})return}c.JSON(200, gin.H{"msg": cookie})})r.Run(":8080")
}

1.4 Cookie的缺点

  • 不安全,明文
  • 增加带宽消耗
  • 可以被禁用
  • cookie有上限

1. Sessions

gorilla/sessions为自定义session后端提供cookie和文件系统session以及基础结构。

主要功能是:

  • 简单的API:将其用作设置签名(以及可选的加密)cookie的简便方法。
  • 内置的后端可将session存储在cookie或文件系统中。
  • Flash消息:一直持续读取的session值。
  • 切换session持久性(又称“记住我”)和设置其他属性的便捷方法。
  • 旋转身份验证和加密密钥的机制。
  • 每个请求有多个session,即使使用不同的后端也是如此。
  • 自定义session后端的接口和基础结构:可以使用通用API检索并批量保存来自不同商店的session。

代码:

package mainimport ("fmt""net/http""github.com/gorilla/sessions"
)// 初始化一个cookie存储对象
// something-very-secret应该是一个你自己的密匙,只要不被别人知道就行
var store = sessions.NewCookieStore([]byte("something-very-secret"))func main() {http.HandleFunc("/save", SaveSession)http.HandleFunc("/get", GetSession)err := http.ListenAndServe(":8080", nil)if err != nil {fmt.Println("HTTP server failed,err:", err)return}
}func SaveSession(w http.ResponseWriter, r *http.Request) {// Get a session. We're ignoring the error resulted from decoding an// existing session: Get() always returns a session, even if empty.// 获取一个session对象,session-name是session的名字session, err := store.Get(r, "session-name")if err != nil {http.Error(w, err.Error(), http.StatusInternalServerError)return}// 在session中存储值session.Values["foo"] = "bar"session.Values[42] = 43// 保存更改session.Save(r, w)
}
func GetSession(w http.ResponseWriter, r *http.Request) {session, err := store.Get(r, "session-name")if err != nil {http.Error(w, err.Error(), http.StatusInternalServerError)return}foo := session.Values["foo"]fmt.Println(foo)
}

3. 结构体验证

gin自带了数据验证的功能,可以不用解析数据,减少if else,在代码观赏性上会好看很多

package mainimport ("fmt""github.com/gin-gonic/gin""time"
)type Person struct {//不能为空并且大于10Age      int       `form:"age" binding:"required,gt=10"`Name     string    `form:"name" binding:"required"`Birthday time.Time `form:"birthday" time_format:"2006-01-02" time_utc:"1"`
}func main() {r := gin.Default()// // 检查登录r.GET("/home", func(c *gin.Context) {var person Personif err := c.ShouldBind(&person); err != nil {c.String(500, fmt.Sprint(err))return}c.String(200, fmt.Sprintf("%#v", person))})r.Run(":8080")
}
  • Age int `form:“age” binding:“required,gt=10”

    binding标签属性就表示验证内容

    • required——必填
    • gt——值必须大于xx

    存在多个验证器时,应当以 “ , ” 隔开

验证器说明示例
-忽略字段binding:“-”
required必填字段binding:“required”
min最小长度binding:“min=10”
max最大长度binding:“max=10”
|binding:“rgb”
structonly如果有嵌套,可以决定只验证结构体上的binding:“structonly”
omitempty省略空,如果为空,则不会继续验证该字段上其他的规则,只有不为空才会继续验证其他的
len长度binding:“len=10”
eq等于binding:“eq=10”
ne不等于binding:“ne=10”
gt大于binding:“gt=10”
lt小于binding:“lt=10”
lte小于等于binding:“lte=10”
eqfield等于其他字段的值Password string binding:"eqfield=ConfirmPassword"
nefield不等于其他字段的值
eqcsfield类似eqfield,它会验证相对于顶层结构提供的字段binding:"eqcsfield = InnerStructField.Field
url字符串值包含有效的网址,必须包含http://等
uri字符串值包含有效的uri. 它将接受golang请求uri接受的任何uri
alpha字符串值仅包含字母字符
alphanum字符串值仅包含字母数字字符
numeric字符串值包含基本数字值。基本不包括指数等…
email字符串值包含有效的电子邮件
contains字符串值包含子字符串值contains=@
excludes字符串值不包含子字符串值excludes = @
containsany包含所有containsany =!@#?
excluderune字符串值不包含提供的符号excluderune = @

注意:gt、gte、lt、lte等都可以用于时间的比较,后面不需要跟值,直接binding:“gt”,表示大于当前utc时间

4. 自定义验证

package mainimport ("net/http""reflect""github.com/gin-gonic/gin""github.com/gin-gonic/gin/binding""gopkg.in/go-playground/validator.v8"
)/*对绑定解析到结构体上的参数,自定义验证功能比如我们要对 name 字段做校验,要不能为空,并且不等于 admin ,类似这种需求,就无法 binding 现成的方法需要我们自己验证方法才能实现 官网示例(https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Custom_Functions)这里需要下载引入下 gopkg.in/go-playground/validator.v8
*/
type Person struct {Age int `form:"age" binding:"required,gt=10"`// 2、在参数 binding 上使用自定义的校验方法函数注册时候的名称Name    string `form:"name" binding:"NotNullAndAdmin"`Address string `form:"address" binding:"required"`
}// 1、自定义的校验方法
func nameNotNullAndAdmin(v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {if value, ok := field.Interface().(string); ok {// 字段不能为空,并且不等于  adminreturn value != "" && !("5lmh" == value)}return true
}func main() {r := gin.Default()// 3、将我们自定义的校验方法注册到 validator中if v, ok := binding.Validator.Engine().(*validator.Validate); ok {// 这里的 key 和 fn 可以不一样最终在 struct 使用的是 keyv.RegisterValidation("NotNullAndAdmin", nameNotNullAndAdmin)}/*curl -X GET "http://127.0.0.1:8080/testing?name=&age=12&address=beijing"curl -X GET "http://127.0.0.1:8080/testing?name=lmh&age=12&address=beijing"curl -X GET "http://127.0.0.1:8080/testing?name=adz&age=12&address=beijing"*/r.GET("/5lmh", func(c *gin.Context) {var person Personif e := c.ShouldBind(&person); e == nil {c.String(http.StatusOK, "%v", person)} else {c.String(http.StatusOK, "person bind err:%v", e.Error())}})r.Run()
}

5. ❤️GoGin框架——前文链接

Gin框架学习参考网站:gin框架·Go语言中文文档

  • (Go Gin)基于Go的WEB开发框架,GO Gin是什么?怎么启动?本文给你答案
  • (Go Gin)Gin学习笔记(二):路由配置、基本路由、表单参数、上传单个文件、上传多个文件、浅扒路由原理
  • (Go Gin)Gin学习笔记(三):数据解析和绑定,结构体分析,包括JSON解析、form解析、URL解析,区分绑定的Bind方法
  • (Go Gin)Gin学习笔记(四):数据渲染、返回JSON、浅.JSON()源码、中间件、Next()方法

6. 💕👉博客专栏

  • Golang专栏-包含基础、Gin、Goam等知识
  • 云原生专栏-包含k8s、docker等知识
  • 从0开始学习云计算-华为HCIP证书
  • JUC专栏-带你快速领悟JUC的知识!
  • JVM专栏-深入Java虚拟机,理解JVM的原理
  • 基于Java研究 数据结构与算法-包含贪心算法、加权图、最短路径算法等知识
  • Docker专栏-上手热门容器技术Docker
  • SpringBoot专栏-学习SpringBoot快速开发后端
  • 项目管理工具的学习-设计技术:Maven、Git、Gradle等相关管理工具
  • JavaSE-全面了解Java基础
  • JS专栏-使用JS作的一部分实例~
  • 使用CSS所作的一部分案例

相关文章:

  • 合并多个Excel文件到一个文件,并保留格式
  • 区块链+医疗:破解数据共享困局,筑牢隐私安全防线
  • Copilot 祝你走在AI前沿:2025 年 4 月动态
  • HTML5好看的水果蔬菜在线商城网站源码系列模板8
  • Copilot总结Word长文档功能更新升级
  • PCB设计工艺规范(一)概述
  • MCP Server 的 Stdio 与 SSE:两种通信方式的本质差异与技术选型指南
  • Linux Nginx网站服务【完整版】
  • 宝塔面板运行docker的jenkins
  • leetcode76
  • a-upload组件实现文件的上传——.pdf,.ppt,.pptx,.doc,.docx,.xls,.xlsx,.txt
  • [计算机科学#6]:从锁存器到内存,计算机存储的构建与原理
  • 安装kubernetes 1.33版本
  • C++负载均衡远程调用学习之Reactor事件触发机制
  • 基于用户场景的汽车行驶工况构建:数据驱动下的能耗优化革命
  • Unity编辑器扩展之导出项目中所有Script里面的文本内容
  • SpringBoot+EasyExcel+Mybatis+H2实现导入
  • Spring Security 6
  • Android学习总结之算法篇六(数组和栈)
  • 毕业论文 | 基于C#开发的NMEA 0183协议上位机
  • 滨江集团:一季度营收225.07亿元,净利润9.75亿元
  • 最高法强化涉新就业形态民事案件审判指导:推动出台司法解释
  • 安徽省公安厅原副厅长刘海石主动投案,正接受审查调查
  • 京东美团开打,苦了商家?
  • 全球首台环形CT直线加速器在沪正式开机,系我国自主研发
  • 秦洪看盘|短线热点降温,A股回落整固