cookie

Web开发中一个很重要的议题就是如何做好用户的整个浏览过程的控制,因为HTTP协议是无状态的,所以用户的每一次请求都是无状态的,我们不知道在整个Web操作过程中哪些连接与该用户有关,我们应该如何来解决这个问题呢?Web里面经典的解决方案是cookie和session,cookie机制是一种客户端机制,把用户数据保存在客户端,而session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构来保存信息,每一个网站访客都会被分配给一个唯一的标志符,即sessionID,它的存放形式无非两种:要么经过url传递,要么保存在客户端的cookies里。当然,你也可以将Session保存到数据库里,这样会更安全,但效率方面会有所下降。

一、cookie的介绍

session和cookie是网站浏览中较为常见的两个概念,也是比较难以辨析的两个概念,但它们在浏览需要认证的服务页面以及页面统计中却相当关键。我们先来了解一下cookie怎么来的?考虑这样一个问题:

如何抓取一个访问受限的网页?如新浪微博好友的主页,个人微博页面等。

显然,通过浏览器,我们可以手动输入用户名和密码来访问页面,而所谓的“抓取”,其实就是使用程序来模拟完成

同样的工作,因此我们需要了解“登陆”过程中到底发生了什么。

当用户来到微博登陆页面,输入用户名和密码之后点击“登录”后浏览器将认证信息POST给远端的服务器,服务器执行验证逻辑,如果验证通过,则浏览器会跳转到登录用户的微博首页,在登录成功后,服务器如何验证我们对其他受限制页面的访问呢?因为HTTP协议是无状态的,所以很显然服务器不可能知道我们已经在上一次的HTTP请求中通过了验证。当然,最简单的解决方案就是所有的请求里面都带上用户名和密码,这样虽然可行,但大大加重了服务器的负担(对于每个request都需要到数据库验证),也大大降低了用户体验(每个页面都需要重新输入用户名密码,每个页面都带有登录表单)。既然直接在请求中带上用户名与密码不可行,那么就只有在服务器或客户端保存一些类似的可以代表身份的信息了,所以就有了cookie与session。

cookie,简而言之就是在本地计算机保存一些用户操作的历史信息(当然包括登录信息),并在用户再次访问该站点时浏览器通过HTTP协议将本地cookie内容发送给服务器,从而完成验证,或继续上一步操作。

cookie的原理图:

Cookie是由浏览器维持的,存储在客户端的一小段文本信息,伴随着用户请求和页面在Web服务器和浏览器之间传递。用户每次访问站点时,Web应用程序都可以读取cookie包含的信息。浏览器设置里面有cookie隐私数据选项,打开它,可以看到很多已访问网站的cookies,如下图所示:

cookie是有时间限制的,根据生命期不同分成两种:会话cookie持久cookie

如果不设置过期时间,则表示这个cookie生命周期为从创建到浏览器关闭止,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览会话期的cookie被称为会话cookie。会话cookie一般不保存在硬盘上而是保存在内存里。

如果设置了过期时间(setMaxAge(606024)),浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间。存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存的cookie,不同的浏览器有不同的处理方式。

二、Go使用cookie

Go语言中通过net/http包中的SetCookie来设置:

http.SetCookie(w ResponseWriter, cookie *Cookie)

w表示需要写入的response,cookie是一个struct,让我们来看一下cookie对象是怎么样的

type Cookie struct {Name  stringValue stringPath       string    // optionalDomain     string    // optionalExpires    time.Time // optionalRawExpires string    // for reading cookies only// MaxAge=0 means no 'Max-Age' attribute specified.// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'// MaxAge>0 means Max-Age attribute present and given in secondsMaxAge   intSecure   boolHttpOnly boolRaw      stringUnparsed []string // Raw text of unparsed attribute-value pairs
}

我们来看一个例子,如何设置cookie,以及获取cookie

package mainimport ("net/http""fmt"
)func main() {http.HandleFunc("/setcookie", SetCookie)http.HandleFunc("/getcookie", GetCookie)http.ListenAndServe("localhost:8080", nil)}func SetCookie(w http.ResponseWriter, r *http.Request) {//设置cookiecookie := http.Cookie{Name: "name", Value: "hanru", Path: "/", MaxAge: 60}http.SetCookie(w, &cookie)w.Write([]byte("write cookie ok"))}//Go读取cookie
func GetCookie(w http.ResponseWriter, r *http.Request) {cookie2, _ := r.Cookie("name")fmt.Fprint(w, cookie2)//还有另外一种读取方式//for _, cookie := range r.Cookies() {//  fmt.Fprint(w, cookie.Name)//}
}

运行服务器后,打开浏览器输入地址:http://127.0.0.1:8080/setcookie

运行结果如下:

在chrome浏览器中执行:http://127.0.0.1:8080/setcookie, 触发go服务执行设置cookie的动作, 浏览器收到这个信息后, 真正执行设置cookie, 在chrome中可查(chrome://settings/content/cookies目录中的localhost域名中查), 如下:

可以看到,过期时间是60s, 60s后再次查的时候, 就没有name对应的cookie项了。

接下来,我们获取一下cookie,要在设置cookie的60s内进行获取,否则就取不到了。

然后打开浏览器,输入网址:http://127.0.0.1:8080/getcookie

运行效果如下:

我们等cookie过期消失, 然后再来玩抓包。 好,现在没有name对应的cookie了, 我们连续两次执行:http://127.0.0.1:8080/setcookie, 服务端tcpdump抓包,两次的请求和响应依次如下:

第一次:

第二次:

可以看到,第一次请求时, 浏览器发出的请求中不带cookie, 因为浏览器压根就没有这项cookie, 在go服务端的回包中携带了Set-Cookie首部, 浏览器收到这个信息后,将其写入到浏览器本地, 形成cookie。

第二次请求时(因cookie的过期时间设置为了60s, 故必须在60s内发起第二次请求), 此时, 浏览器的http请求中自动携带了cookie信息,go服务端也能收到这个信息。

由此可见, cookie不过是浏览器端的一个环境变量而已, 仅此而已。cookie值存在于浏览器所在的本地电脑中。 而所谓的服务端设置cookie, 其实是服务端给浏览器发送对应的设置cookie信息, 由浏览器来真正执行设置cookie的操作, 存于本地电脑磁盘中。

转载自https://www.chaindesk.cn/witbook/17/265,谢谢韩老师

转载于:https://www.cnblogs.com/Paul-watermelon/articles/11030894.html

【GoWeb开发实战】Cookie相关推荐

  1. 【GoWeb开发实战】Beego的路由控制

    Beego的路由控制 二.路由控制 web框架中,路由是重要的一环,对于beego的路由配置如何? 2.1 默认路由 让我们从入口文件main.go先分析起来吧: package mainimport ...

  2. goweb开发实战笔记(一)

    目录

  3. 【Python3网络爬虫开发实战】3-基本库的使用 1.2-处理异常

    前一节我们了解了请求的发送过程,但是在网络不好的情况下,如果出现了异常,该怎么办呢?这时如果不处理这些异常,程序很可能因报错而终止运行,所以异常处理还是十分有必要的. urllib的error模块定义 ...

  4. JAVA WEB开发实战-张晨光-专题视频课程

    JAVA WEB开发实战-379人已学习 课程介绍         走进JSP.掌握JSP语法.JSP内置对象.Servlet技术.综合实验(一)--JSP使用Model2实现登录模块.EL表达式语言 ...

  5. Visual Basic开发实战1200例(第Ⅱ卷)pdf

    下载地址:网盘下载 内容简介 编辑 本书以开发人员在项目开发中经常遇到的问题和必须掌握的技术为核心,介绍了应用Visual Basic进行程序开发的多方面的知识和技巧,主要包括Visual Basic ...

  6. 【Python开发】Flask开发实战:个人博客(三)

    Flask开发实战:个人博客(三) 在[Python开发]Flask开发实战:个人博客(一) 中,我们已经完成了 数据库设计.数据准备.模板架构.表单设计.视图函数设计.电子邮件支持 等总体设计的内容 ...

  7. Flask Web开发:基于Python的Web应用开发实战

    <Flask Web开发:基于Python的Web应用开发实战> 虽然简单的网站(Flask+Python+SAE)已经上线,但只是入门.开发大型网站,系统地学习一遍还是有必要的. 201 ...

  8. java web开发实战经典 源码_李兴华 java_web开发实战经典 源码 完整版收集共享

    李兴华 java_web开发实战经典 源码 完整版收集共享 01f8a7  在  2018-11-07 20:41:33  上传  10.92 MB 第1章 JAVA WEB开发简介 1.1.WEB发 ...

  9. 视频教程-JAVA WEB开发实战-Java

    JAVA WEB开发实战 主要研究方向为J2EE..net .数据库 .前端.Android,曾经服务过大型上市国企IT部门,软件企业联合创始人,对软件研发管理.市场营销有自己独特思想体系! 张晨光 ...

最新文章

  1. 对ARM异常(Exceptions)的理解
  2. android开发--详解ListView,动态添加,删除Adapter中的数据项
  3. tab s6 linux on dex,S Pen + DeX模式 三星Galaxy Tab S6让你秒变办公达人
  4. MYSQL的索引类型:PRIMARY, INDEX,UNIQUE,FULLTEXT,SPAIAL 有什么区别?各适用于什么场合?
  5. 望城2019年华为软件云项目_今天,华为、京东两大项目在长沙开工
  6. 如何在Swiper内制作CSS3动画效果
  7. Linux中Mysql root用户看不到mysql库问题解决方式
  8. Leetcode 133.克隆图
  9. 数据治理需要注意哪些问题
  10. 10.15 iptables filter表小案例;10.16—10.18 iptables nat
  11. ActiveMQ 无法启动 提示端口被占用 解决方案
  12. 国家社科基金项目清单、申报书填写指南和课题申报书模板
  13. 麦克风阵列技术(转载)
  14. 硬件科普系列之硬盘——总线、协议、接口和固态硬盘篇
  15. 开源spider一览(zz)
  16. Android传感器、语音识别、定位系统、Google Map API、快捷方式、widget编程总结及示例...
  17. 本科课程【java程序设计】实验2 - 类与对象编程练习
  18. sql2000 mysql 兼容_sql2005兼容2000 | 向后兼容组件
  19. webservice拦截器 查看消息包(soap)
  20. win10系统版本Windows Media Player不见

热门文章

  1. 数据结构学习笔记(一)——《大话数据结构》
  2. 老生常谈:抽象工厂模式
  3. 清除防火墙所有配置规则
  4. Spring Cloud Sleuth进阶实战
  5. MySQL-ProxySQL中间件(一)| ProxySQL基本概念
  6. 【pl/sql番外篇】 存储过程 游标
  7. linux 下实现负载均衡群集(NAT方式)
  8. 数据旋转及DB2递归的应用
  9. python 开发api_使用FastAPI和Python快速开发高性能API
  10. 导入数据库怎么导入_导入必要的库