不久前用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存储 模拟登陆问题的更多相关文章

  1. 爬虫之 cookie , 验证码,模拟登陆,线程

    需求文档的定制 糗事百科的段子内容和作者(xpath的管道符)名称进行爬取,然后存储到mysql中or文本 http://sc.chinaz.com/jianli/free.html爬取简历模板 HT ...

  2. js读写Cookie问题(Cookie存储时长、Cookie存储域)汇总

    在采集网站用户行为数据/使用js对用户行为做交互时,经常会使用到Cookie,了解Js Cookie的读写,以及一些细节,非常重要.   什么是Cookie 所谓Cookie,只是一条极为短小的信息, ...

  3. 使用OKHttp模拟登陆知乎,兼谈OKHttp中Cookie的使用!

    本文主要是想和大家探讨技术,让大家学会Cookie的使用,切勿做违法之事! 很多Android初学者在刚开始学习的时候,或多或少都想自己搞个应用出来,把自己学的十八般武艺全都用在这个APP上,其实这个 ...

  4. cookie : 存储数据

    cookie : 存储数据,当用户访问了某个网站(网页)的时候,我们就可以通过cookie来像访问者电脑上存储数据 1.不同的浏览器存放的cookie位置不一样,也是不能通用的 2.cookie的存储 ...

  5. python 模拟登陆,请求包含cookie信息

    需求: 1.通过GET方法,访问URL地址一,传入cookie参数 2.根据地址一返回的uuid,通过POST方法,传入cooki参数 实现思路: 1.理解http的GET和POST差别 (网上有很多 ...

  6. SetCookies, cookie规范注册表和cookie存储将会优先于设置在HTTP客户端级别中默认的那些

    遇到下面问题解决方法: Hey? 404 抱歉,你输入的网址可能不正确,或者该网页不存在. 7 秒后返回首页 使用独立的本地执行上下文来实现对每个用户(或每个线程)状态的管理. 定义在本地内容中的co ...

  7. 通过js来设置cookie和读取cookie,实现登陆时记住密码的功能

    function setCookie(){ //设置cookie var loginCode = $("#login_code").val(); //获取用户名信息 var pwd ...

  8. Memcache+cookie实现模拟session

    上一片讲到Memcached在Windows上的安装,和用Telnet工具进行命令操作,在稍微了解了原理之后,我也就开始尝试着用程序来对Memcached进行操作.这一篇分为两个部分,第一部分是用.n ...

  9. selenium3.7+ python3 添加cookie模拟登陆

    一.背景介绍 最近做一个爬虫项目,用selenium调用浏览器去获取渲染后的源码,但是每次登陆都需要手机验证,这真的是头痛啊,这种验证方式不要想着去破解,还是老老实实用手机收验证码去吧!反正我是不知道 ...

随机推荐

  1. Git和GitHub在线学习资源整理

    电子书 GotGitHub Git Workflow 沉浸式学习Git 文章 GitHub Fundamental visual-git-guide 图形化的Git参考手册 Linux下使用git命令 ...

  2. java web编程 servlet2

    一般在开发的过程中主要用一个doGet和doPost方法, http就是超文本传输协议,这是java API对servlet的描述 : 一般我们调用的方法细则如下 : service一分为二reque ...

  3. 常用的js加密

    https://github.com/hellobajie/AES-of-JavaScript    此为js的 AES加密方式,两个加密文档,可当做扣js必备

  4. 【转】解决maven无法加载本地lib/下的jar包问题(程序包XXX不存在)

    原文链接:https://www.cnblogs.com/adeng/p/7096484.html 这次一个项目用到maven编译,我在本地开发的时候jar包都是放在WEB-INF/lib目录下,通过 ...

  5. [转]Python测试框架对比----unittest, pytest, nose, robot framework对比

      测试框架 什么是框架? 框架(Framework)是整个或部分系统的可重用设计,框架是用来解决代码的组织及运行控制问题的. 在我们编写自动化脚本的时候,经常需要读取配置文件,读取数据文件,发送请求 ...

  6. vue项目中要实现展示markdown文件[转载]

    转载 版权声明:本文为CSDN博主「齐天二圣」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog.csdn.net/nihaoa5 ...

  7. logstash-output-jdbc遇到connection is not available,request time out after 10000ms的问题解决

    上一篇logstash-output-jdbc使用中提到“运行bin/logstash -f test.conf时可能提示注册插件失败”,通过分析详细的错误日志,发现其赫然写着“connection ...

  8. piplinedb 团队加入confluen

    这个消息对于使用pipelinedb 的人来说,可能有点不好,因为官方已经明确说明了,pipelinedb 截止到1.0 版本,将不再维护了, 基本就要靠社区了,但是pipelinedb 团队还是比较 ...

  9. leetcode解题报告(26):Add Binary

    描述 Given two binary strings, return their sum (also a binary string). For example, a = "11" ...

  10. 一个有趣的js隐式转换的问题

    一个有趣的js隐式转换的问题 在chrome的控制台中打印一下表达式 [] + {} //结果为 [object object] 然后调整顺序打印 {} + [] //结果为 0 然后将两个表达式组合 ...