不久前用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. Github的fork进行同步

    最近项目要求每个开发人员都有自己fork,需要在自己的fork下进行开发.这样就涉及的到fork和原仓库的同步问题. 在网上查找到fork和原仓库同步的方法,如下转载自网上查找的内容,使用终端命令行进 ...

  2. Python绘制拓扑图(无向图)、有向图、多重图。最短路径计算

    前言: 数学中,“图论”研究的是定点和边组成的图形. 计算机中,“网络拓扑”是数学概念中“图”的一个子集.因此,计算机网络拓扑图也可以由节点(即顶点)和链路(即边)来进行定义和绘制. 延伸: 无向图 ...

  3. datatables 自定义排序

    参考:https://datatables.net/examples/plug-ins/sorting_manual $.fn.dataTable.ext.type.order['salary-gra ...

  4. TFTP启动内核、设备树,NFS启动FS

    一.软硬件平台 1.开发板:创龙AM3359核心板,网口采用RMII形式. 2.UBOOT版本:U-Boot-2016.05,采用FDT和DM. 3.交换芯片MARVELL的88E6321. 二.问题 ...

  5. mqtt服务搭建(emqx,原emq)

    系统环境: ubuntu 18.04server lts 目标系统IP地址(可访问):192.168.1.31 emqx版本: v3.2.3 打开网页,根据目标系统和emqx版本选择好安装包.这里我选 ...

  6. vue 关于props 父组件传值

    swiper.vue  子组件 info.vue 父组件 swiper.vue<template> <div class="swiper-wrap" @mouse ...

  7. 微信小程序~App.js中登录

    (1)初始化项目中App.js登录代码 // 登录 wx.login({ success: res => { // 发送 res.code 到后台换取 openId, sessionKey, u ...

  8. 怎么给win10进行分区?

    新安装的win10系统的朋友,对于win10系统分区不满意应该如何是好呢?今天给大家介绍两种win10系统分区的方法,一个是windows自带分区管理软件来操作;另一个就是简单方便的分区助手来帮助您进 ...

  9. Hibernate的关联关系映射

    技术分析之Hibernate的关联关系映射之一对多映射(重点)        1. JavaWEB中一对多的设计及其建表原则        2. 先导入SQL的建表语句                 ...

  10. md5关于加密

    # 导入hashlib模块 import hashlib # 获取MD5对象 # 不加盐操作 # md5 = hashlib.md5() # 加盐操作 md5 = hashlib.md5('wenwe ...