首页 📡web后端

" 对于开发者,cookie的是web开发里程上的一大发明,cookie是小甜点,绝不是恶魔。但是,如果使用不当,小甜点发霉了一样会有毒。"

这样一句话,揭露了cookie的两个特点,实用和安全性。不管你知不知道cookie/session,你一定经历过这样的事——点开不久前登录过的网站,发现自己无需重复登录直接进入主页。曾有同学问过我这是怎么实现的,总的来讲,cookie/session是web领域常用的两种技术,实现对用户会话的跟踪。那么,cookie究竟是什么?session又是在怎么的背景下引入的?他们在web开发的过程中,又该怎样高效使用呢?下面这篇文章,将对cookie与session进行较为详细的分析。

一、cookie

(一)什么是cookie?

Cookie是网站服务器把少量的文本数据存储到客户端的硬盘或内存,或是从客户端读取数据的一种技术。浏览某个网站时,服务器会向你的电脑发送cookie,记录了ID password等,当你发起请求时会带上cookie,网站读取该cookie,从而实现读取你的信息进行认证。那么也就有了接下来看到的一幕——“已登录成功,无需重复登录”类似的文段。把自己想象成一个游客,把cookie想象成你的通行证,你需要携带自己的通行证去游览,而正是这个通行证,记录了你的个人信息。
cookie具有不可跨域名性,cookie在客户端通过浏览器进行管理,因此不同的浏览器之间不能跨域进行读取和认证,这也是我们写cookie时一定需要引起重视的一点。
而需要注意的是,一个用户的所有请求操作,都应该属于一个会话,不能混淆不同的会话。在session出现之前,其实基本上所有的网站都采用cookie技术来跟踪用户的会话。

请输入图片描述

cookie中常用的属性见下表:

请输入图片描述

(二)cookie的代码实现(基于Golang语言)

1、调用包

很简单的一个http网络包import "net/http"即可。

2、设置cookie

func setCookieHandler(c *gin.Context) {
    test_cookie := &http.Cookie{
        Name:     "test_cookie",
        Value:    "username",
        Path:     "/",
        HttpOnly: false,
        MaxAge:   3600,
    }
    c.Writer.Header().Set("Set-Cookie", test_cookie.String())
    //http.SetCookie(c.Writer,test_cookie)
}

请输入图片描述

3、读取浏览器端的cookie值

func getCookieHandler(c *gin.Context) {
    test_cookie, _ := c.Request.Cookie("test_cookie")
    fmt.Println(test_cookie)
}

请输入图片描述

4、在登录函数中生成cookie

func loginHandler(c *gin.Context) {
    username := c.PostForm("username")
    password := c.PostForm("password")
    fmt.Println("Server reveive data:", username, password)

    uid_cookie := &http.Cookie{
        Name:     "uid",
        Value:    username,
        HttpOnly: false,
        MaxAge:   3600,
    }
    c.Writer.Header().Set("Set-Cookie", uid_cookie.String())
}

Postman测试如下:
请输入图片描述

5、cookie的安全问题

cookie是甜点,使用不当就像发霉的小点心有毒。

我们很直观地看见,生成并存储在浏览器中的cookie参数是以username直接存储的,所以为了保证安全性,我们需要对cookie的存储进行加密操作,这个环节!相当重要!为了方便,我们使用github.com/gorilla/securecookie包提供的一个HashKey.
请输入图片描述

    var hashKey = []byte("very-secret")
    var s = securecookie.New(hashKey, nil)
    encoded,_:=s.Encode("test_cookie","test_cookie")

请输入图片描述

二、session

(一)什么是session?

如果理解并会使用cookie了,session理解起来也将是顺理成章的事情,并且你会从session中获取到(更加愉快的)知识!
session是服务器端使用的一种记录客户端状态的机制,在使用过程中增加了服务器的压力,但是不论从用户信息的存储还是提取来说,session也许都是会话跟踪更好的选择。

如果说cookie是检查旅客身上携带的通行证,那么session就是检查工作人员后台的客户明细表。两者都可以实现对用户信息的认证过程,但是信息存储的位置并不相同。

(二)session的代码实现

1、调用包

import "github.com/gin-contrib/sessions"

包的下载通常使用如下两种方式:

  • 终端命令行go get包
    注意cd命令进入相应gowork/src目录下:go get github.com/gin-contrib/sessions
  • Gitbush命令行远程克隆Github包
    对应目录启动Gitbush:git clone https://github.com/gin-contrib/sessions.git

2、设置全局变量store及session的调用

var store = cookie.NewStore([]byte("secret")) //全局store 双引号内写“密钥”规则
func main() {
    r := router()
    r.Run()
}
func router() *gin.Engine {
    r := gin.Default()
    r.Use(sessions.Sessions("sessionId", store)) //调用session
    r.POST("/register", registerHandler)
    r.Get("/rank", rankHandler)

    return r
}

3、初始化session

session := sessions.Default(c)

4、设置session相关参数

设置最大保持时间

option := sessions.Options{MaxAge: 3600}
session.Options(option)

删除session的一种思路

session.Options.MaxAge = -1
//负数即是直接删除session 正数即是设置time
session.Save(r, w)

4、生成session并保存

session.Set("sessionid", username)
err := session.Save()

测试结果如下(由Postman测试):

请输入图片描述

请输入图片描述

5、获取session参数

session := sessions.Default(c)
v := session.Get("sessionid")
fmt.Println("sessionid:", v)

6、分离生成及获取session的函数

func SetSession(c *gin.Context, key string, value string) {
    session := sessions.Default(c)
    session.Set(key, value)
    err := session.Save()
    if err != nil {
        fmt.Println(err)
    }
}

func GetSession(c *gin.Context, key string) string {
    session := sessions.Default(c)
    v := session.Get(key)
    fmt.Println(key, v)
    if v == nil {
        return ""
    }
    return v.(string)
}

三、参考资料

[1] https://github.com/gin-contrib/sessions
[2] Cookie/Session机制详解
[3] Go 实现安全 cookie
[4] Golang Cookie 简介、浅谈golang的http cookie用法



文章评论

目录