【GoWeb开发实战】Cookie

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/393196.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring中WebApplicationInitializer的理解

现在JavaConfig配置方式在逐步取代xml配置方式。而WebApplicationInitializer可以看做是Web.xml的替代&#xff0c;它是一个接口。通过实现WebApplicationInitializer&#xff0c;在其中可以添加servlet&#xff0c;listener等&#xff0c;在加载Web项目的时候会加载这个接口实…

网络摄像头CVE

CVE-2018-9995 rtsp未授权访问 rtsp后缀整理&#xff1a; Axis&#xff08;安讯士&#xff09; rtsp:// 192.168.200.202/axis-media/media.amp?videocodech264&resolution1280x720 rtsp://IP地址/mpeg4/media.amp rtsp://IP地址/安迅士/AXIS-media/media.amp123D-Link …

Elastic-job使用及原理

一、原理 elastic-job有lite版和cloud版&#xff0c;最大的区别是有无调度中心&#xff0c;笔者采用的是lite版本&#xff0c;无中心化。 tips: 第一台服务器上线触发主服务器选举。主服务器一旦下线&#xff0c;则重新触发选举&#xff0c;选举过程中阻塞&#xff0c;只有主服…

BeanShell自动装箱拆箱

“装箱”和“拆箱”是用来描述自动包装一个原始类型到一个包装类以及在必要时解开包装回到原始类型的术语。装箱是 Java 的特性&#xff08;SDK 1.5&#xff09;之一&#xff0c;且 BeanShell 已支持多年。 BeanShell 支持原始类型的装箱和拆箱。比如&#xff1a; int i5; Inte…

安装Docker step by step

1. 系统要求 centos7以上 使用cat /etc/redhat-release查看系统版本&#xff0c;我的Centos 7.6 centos-extra 仓库 enable&#xff0c;默认是打开的 2.安装docker docer安装分为联网安装和离线安装两种安装 方式&#xff0c; 第一种 在有外网环境下安装docker,一般使用yum安…

微信小程序 php配置,微信小程序的配置

我们使用app.json文件来对微信小程序进行全局配置&#xff0c;决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。以下是一个包含了所有配置选项的简单配置app.json{"pages": ["pages/index/index","pages/logs/index"],"wi…

PWA - service worker - Workbox(未完)

Get Started&#xff08;开始&#xff09; 只有get请求才能cache缓存吗&#xff1f;Create and Register a Service Worker File&#xff08;创建和注册 Service Worker&#xff09; Before we can use Workbox, we need to create a service worker file and register it to o…

System类入门学习

第三阶段 JAVA常见对象的学习 System类 System类包含一些有用的字段和方法&#xff0c;他不能被实例化 //用于垃圾回收 public static void gc()//终止正在运行的java虚拟机。参数用作状态码&#xff0c;根据惯例&#xff0c;非0表示异常终止 public static void exit(int stat…

gulpfile php,Laravel利用gulp如何构建前端资源详解

什么是gulp&#xff1f;gulp是新一代的前端项目构建工具&#xff0c;你可以使用gulp及其插件对你的项目代码(less,sass)进行编译&#xff0c;还可以压缩你的js和css代码&#xff0c;甚至压缩你的图片&#xff0c;gulp仅有少量的API&#xff0c;所以非常容易学习。 gulp 使用 st…

8-python自动化-day08-进程、线程、协程篇

本节内容 主机管理之paramiko模块学习 进程、与线程区别python GIL全局解释器锁线程语法join线程锁之Lock\Rlock\信号量将线程变为守护进程Event事件 queue队列生产者消费者模型Queue队列开发一个线程池进程语法进程间通讯进程池 转载&#xff1a;  http://www.cnblogs.co…

select查询语句执行顺序

查询中用到的关键词主要包含六个&#xff0c;并且他们的顺序依次为 select--from--where--group by--having--order by 其中select和from是必须的&#xff0c;其他关键词是可选的&#xff0c;这六个关键词的执行顺序 与sql语句的书写顺序并不是一样的&#xff0c;而是按照下面的…

Python的Virtualenv(虚拟环境)的使用(Windows篇)2

Python的Virtualenv(虚拟环境)的使用&#xff08;Windows篇&#xff09; 2018年04月13日 11:35:01 D_FallMoon 阅读数 771 版权声明&#xff1a;版权所有 装载请注明 …

创建邮箱过程中的问题及解决办法

转自白手起家博客 http://bbs.chinaunix.net/forum.php?modviewthread&tid770141 说明一下&#xff1a;Q代表安装过程中遇到的问题&#xff0c;或者是日志中出现的现象。A&#xff1a;代表解决方法。 Q&#xff1a; Jan 13 11:26:29 mail authdaemond: failed to connect …

跟我一起屏蔽百度搜索页面右侧的内容

苦恼百度搜索热点等冗杂信息很久了&#xff0c;然后今天下定决心解决这个问题了。 第一步&#xff1a;搜索&#xff0c;并安装插件Adblock Plus 第二步&#xff1a;使用拦截器 1.打开拦截器 2.具体使用 点击这一块 添加 转载于:https://www.cnblogs.com/smart-girl/p/11058774.…

鼠标拖拽吸附效果

JavaScript鼠标拖动自动吸附实例 学了几天的JavaScript&#xff0c;自己动手做了一个简单的鼠标拖动的实例&#xff0c;拖动过程中科自动检测与目标容器的距离&#xff0c;在一定的距离范围内可以自动将被拖动的元素加入到目标容器中&#xff0c;希望对开始学习javascript的童鞋…

php修改mysql数据库中的表格,如何修改mysql数据库表?

修改mysql数据库表的方法&#xff1a;使用“ALTER TABLE”语句&#xff0c;可以改变原有表的结构&#xff0c;例如增加字段或删减字段、修改原有字段数据类型、重新命名字段或表、修改表字符集等&#xff1b;语法“ALTER TABLE [修改选项]”。修改数据表的前提是数据库中已经存…

微软最新GDI漏洞MS08-052安全解决方案

微软最新GDI漏洞MS08-052安全解决方案 Simeon微软于九月九日凌晨爆出有史以来最大的安全漏洞MS08-052&#xff0c;通过该漏洞&#xff0c;攻击者可以将木马藏于图片中&#xff0c;网民无论是通过浏览器浏览、还是用各种看图软件打开、或者在即时聊天窗口、电子邮件、Office文档…

DEM轨迹后处理

方法一&#xff1a;直接在paraview中显示 首先在输出颗粒信息的时候保存global ID&#xff1a;然后在paraview中导入vtp数据&#xff08;不要导入pvd&#xff09;&#xff0c;并使用Temporal Particle To Pathlines这个filter&#xff08;可以直接ctrlspace调出搜索框搜索&…

LVS的四种模式的实现

LVS 是四层负载均衡&#xff0c;也就是说建立在 OSI 模型的第四层——传输层之上&#xff0c;传输层上有我们熟悉的 TCP/UDP&#xff0c;LVS 支持 TCP/UDP 的负载均衡。LVS 的转发主要通过修改 IP 地址&#xff08;NAT 模式&#xff0c;分为源地址修改 SNAT 和目标地址修改 DNA…

安卓系统换成linux系统软件,将旧安卓手机打造成“简易linux”机器,并部署AdGuardHome...

从原教程的安装Linux Deploy 完成后&#xff0c;在配置 Linux下载镜像的一些东西时有些许出入。首先&#xff0c;我是用的下载源地址是 http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports 清华的源挺好用的。 其他有出入的配置如图(记得把源地址改清华的&#xff0c;华中科大…