Go -- client 302 自动转 200 问题 cookie存储 模拟登陆问题
不久前用go写了个http client,去模拟某网站(*.com)的登录操作。网站的登录逻辑:1.验证登录账号和密码;2.下发token。此token通过cookie下发;3.redirect到主页(/)。主页对token进行校验,渲染、展示页面信息。简单调用http.DefaultClient.Do(request),并未获取到预期的response,问题究竟出在了什么地方。
net/http.Client 默认自动处理redirect

我们跟踪一下库代码,看一下详细的逻辑。通过函数名,为我们获得一个初步印象:对于“GET”、“HEAD”、“POST”、“PUT”请求,将进行自动重定向。至于“GET”和“HEAD”对于哪些status code进行重定向、“POST”和“PUT”方法又响应哪些status code的重定向呢?关键就在于doFollowingRedirects的第二个入参:shouldRedirectGet和shouldRedirectPost函数。

将case中的常量翻译一下,就是“HEAD”和“GET”方法,响应301、302、303和307;“POST”和“PUT”方法响应302和303。意味着redirect默认是自发执行的,为何登录跳转失败呢?问题出在了cookie上。默认重定向时,并不会保存上次response的cookie,自然不会携带相应的cookie去发起redirect后的请求。
redirect 携带cookie在http.Client中有一个Jar字段,用于存储(内存)cookies。

注释写得很清楚,如果此字段为空,client发起请求时,将不携带cookies且response返回的cookies将被忽略。CookieJar的定义位于net/http的jar.go中,是一个interface。

所谓CookieJar,直白点,就是一个cookie的存储,很自然提供两个方法:SetCookies和Cookies,分别用于set和get操作。net/http/cookiejar中给出了一个CookieJar的实现。

显然Jar中真正用来存储cookies的就是entries这一成员变量了,为一个双map结构。map的第一个key为域名后缀,按照pList(PublicSuffixList)指定的规则来获取;第二个key为cookie name、domain和path拼接而成的一个string。pList可以为空。
无须继续往下,我们已经知晓只要为client设置Jar字段,即可实现redirect的时候携带相应cookie的目的。

自此,问题得以解答。后面再罗嗦一点相关的东西。
jar 的 cookie 匹配规则
实例代码中,通过cookiejar.New(nil)初始化一个cookie jar,即Jar.pList为nil,使用默认的cookie匹配规则。Jar数据结构的介绍中,说明了pList将影响entries map的第一个key,具体的实现为jarKey这个函数。


PublicSuffixList是一个interface,当Jar中为指定此字段时,将采用默认的匹配规则:""作为key(假如域名为,key则为);否则将使用PublicSuffixList的实现类的规则来挑选key,中提供了一种实现,这里不再深究,感兴趣的同学,自行前去观看。
禁止 redirect如果不希望client代替我们做redirect,有什么办法呢?Client数据结构中设计了一个CheckRedirect的字段,此字段是一个函数引用。

从注释中,我们很容易获知禁止redirect的解决方法:CheckRedirect函数简单返回一个http.ErrUseLastResponse即可。这个埋点(CheckRedirect调用)发生在什么位置呢?调用链:http.Do -> c.doFollowingRedirect -> c.checkRedirect。

checkRedirect位于一个for循环中,循环次数由后端redirect的次数和最大允许的递归重试(默认10)次数共同决定。显然,当checkRedirect返回一个http.ErrUseLastResponse的错误后,redirect的循环正常退出。
如何禁止redirect回答完毕。checkRedirect函数,浅显易懂,就不再多介绍。贴出源代码,大家一起再来感受和膜拜一下库作者令人拍案叫绝的设计能力和注释的书写能力!

Go -- client 302 自动转 200 问题 cookie存储 模拟登陆问题的更多相关文章
- 爬虫之 cookie , 验证码,模拟登陆,线程
需求文档的定制 糗事百科的段子内容和作者(xpath的管道符)名称进行爬取,然后存储到mysql中or文本 http://sc.chinaz.com/jianli/free.html爬取简历模板 HT ...
- js读写Cookie问题(Cookie存储时长、Cookie存储域)汇总
在采集网站用户行为数据/使用js对用户行为做交互时,经常会使用到Cookie,了解Js Cookie的读写,以及一些细节,非常重要. 什么是Cookie 所谓Cookie,只是一条极为短小的信息, ...
- 使用OKHttp模拟登陆知乎,兼谈OKHttp中Cookie的使用!
本文主要是想和大家探讨技术,让大家学会Cookie的使用,切勿做违法之事! 很多Android初学者在刚开始学习的时候,或多或少都想自己搞个应用出来,把自己学的十八般武艺全都用在这个APP上,其实这个 ...
- cookie : 存储数据
cookie : 存储数据,当用户访问了某个网站(网页)的时候,我们就可以通过cookie来像访问者电脑上存储数据 1.不同的浏览器存放的cookie位置不一样,也是不能通用的 2.cookie的存储 ...
- python 模拟登陆,请求包含cookie信息
需求: 1.通过GET方法,访问URL地址一,传入cookie参数 2.根据地址一返回的uuid,通过POST方法,传入cooki参数 实现思路: 1.理解http的GET和POST差别 (网上有很多 ...
- SetCookies, cookie规范注册表和cookie存储将会优先于设置在HTTP客户端级别中默认的那些
遇到下面问题解决方法: Hey? 404 抱歉,你输入的网址可能不正确,或者该网页不存在. 7 秒后返回首页 使用独立的本地执行上下文来实现对每个用户(或每个线程)状态的管理. 定义在本地内容中的co ...
- 通过js来设置cookie和读取cookie,实现登陆时记住密码的功能
function setCookie(){ //设置cookie var loginCode = $("#login_code").val(); //获取用户名信息 var pwd ...
- Memcache+cookie实现模拟session
上一片讲到Memcached在Windows上的安装,和用Telnet工具进行命令操作,在稍微了解了原理之后,我也就开始尝试着用程序来对Memcached进行操作.这一篇分为两个部分,第一部分是用.n ...
- selenium3.7+ python3 添加cookie模拟登陆
一.背景介绍 最近做一个爬虫项目,用selenium调用浏览器去获取渲染后的源码,但是每次登陆都需要手机验证,这真的是头痛啊,这种验证方式不要想着去破解,还是老老实实用手机收验证码去吧!反正我是不知道 ...
随机推荐
- C语言编译器
我们分两部分介绍C语言的编译器,分别是桌面操作系统和嵌入式操作系统. 桌面操作系统 对于当前主流桌面操作系统而言,可使用 Visual C++.GCC 以及 LLVM Clang 这三大编译器. Vi ...
- UEditor 在 Layer 模态框中无法使用问题
问题: 解决方法: 在 使用 ueditor 的页面顶部加入js代码: window.UEDITOR_HOME_URL = "__STATIC__/path/to/ueditor/&quo ...
- 04 -- 元类和ORM
本篇主要介绍元类,为什么说一切皆对象:如何动态的创建类等:以及ORM,即什么是ORM等知识 一.元类 1.1 在Python中一切皆对象 在学习元类中我们首先需要了解一个概念-- python中一切皆 ...
- 怎么查看二进制文件内容?linux下nm命令告诉你!
linux下强大的文件分析工具 -- nm 什么是nm nm命令是linux下自带的特定文件分析工具,一般用来检查分析二进制文件.库文件.可执行文件中的符号表,返回二进制文件中各段的信息. 目标文件. ...
- js HTTP 下载 处理 api 请求 返回数据流
axios({ method: 'post', url: 'url....', data:{}, timeout: 1000*60, responseType: 'blob',// 此选项必须设置 否 ...
- 零基础如何学好python之变量
想要自学python,变量(variable)是必经之路,它是学习python初始时,就会接触到的一个新的知识点,也是一个需要熟知的概念.python是一种动态类型语言,在赋值的执行中可以绑定不同类型 ...
- python get/post接口使用
背景: 使用python调用get post接口,入参.出参都需要转换,在使用时经常会忘记其中的一步,本文用来记录,后面再使用时直接参考使用 代码如下 post: headers = {'Conten ...
- 神经网络(4)---神经网络是如何帮助我们学习复杂的nonlinear hypotheses
神经网络是如何一步步进行计算的,以及对计算过程的向量化 Z1(2),Z2(2),Z3(2) are just weighted linear combination of input value x1 ...
- Java线程调度方式
在Java多线程环境中,为保证所有线程的执行能按照一定的规则执行,JVM实现了一个线程调度器,它定义了线程调度的策略,对于CPU运算的分配都进行了规定,按照这些特定的机制为多个线程分配CPU的使用权. ...
- CentOS7 部署 ElasticSearch7.0.1 集群
环境 主机名 IP 操作系统 ES 版本 test1 192.168.1.2 CentOS7.5 7.0.1 test2 192.168.1.3 CentOS7.5 7.0.1 test3 192.1 ...