热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Golang源码COOKIEBUG追查

最近的项目从golang0.9升级到golang1.13后,项目中出现了很特殊的现象,在APP里,用户登录后访问页面正常,用户不登录,报错。大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

起因

最近的项目从golang0.9升级到golang1.13后,项目中出现了很特殊的现象,在APP里,用户登录后访问页面正常,用户不登录,报错。

处理过程

  1. Charles抓包发现,登录的情况下,服务返回的是protobuf的数据,未登录情况下返回的是json结构。服务是根据COOKIE中传入的数据来返回对应的数据类型。初步断定未登录情况下无法获取到COOKIE

  2. 检查登录和未登录情况下COOKIE的区别。

    • 登录: serviceToken=abc ;type=protobuf;session=123
    • 未登录:;type=protobuf;session=123

    serviceToken是登录后的验证信息,用户如果未登录,数据不存在,但是分号却存在。初步怀疑是golang版本引起

  3. 在代码不变的情况下,使用不同golang版本生成服务,使用脚本进行测试

     

    确定是golang版本问题

  4. 查看源码,在net/http/COOKIE.go中,可以看到

    • golang1.12将COOKIE直接做了分割strings.Split(strings.TrimSpace(line), ";"),所以无论分号在什么位置都能解析出来
    • 在golang1.13中 if splitIndex := strings.Index(line, ";"); splitIndex > 0 ,使用这种切割方式,如果引号位于第一个,整个获取过程便结束了,无法获得正确的COOKIE值

    golang1.12

    // readCOOKIEs parses all "COOKIE" values from the header h and
    // returns the successfully parsed COOKIEs.
    //
    // if filter isn't empty, only COOKIEs of that name are returned
    func readCOOKIEs(h Header, filter string) []*COOKIE {
       lines, ok := h["COOKIE"]
       if !ok {
          return []*COOKIE{}
       }
    
       COOKIEs := []*COOKIE{}
       for _, line := range lines {
          parts := strings.Split(strings.TrimSpace(line), ";")
          if len(parts) == 1 && parts[0] == "" {
             continue
          }
          // Per-line attributes
          for i := 0; i  

    golang1.13

    // readCOOKIEs parses all "COOKIE" values from the header h and
    // returns the successfully parsed COOKIEs.
    //
    // if filter isn't empty, only COOKIEs of that name are returned
    func readCOOKIEs(h Header, filter string) []*COOKIE {
       lines := h["COOKIE"]
       if len(lines) == 0 {
          return []*COOKIE{}
       }
    
       COOKIEs := make([]*COOKIE, 0, len(lines)+strings.Count(lines[0], ";"))
       for _, line := range lines {
          line = strings.TrimSpace(line)
          var part string
          for len(line) > 0 { // continue since we have rest
             if splitIndex := strings.Index(line, ";"); splitIndex > 0 {
                part, line = line[:splitIndex], line[splitIndex+1:]
             } else {
                part, line = line, ""
             }
             part = strings.TrimSpace(part)
             if len(part) == 0 {
                continue
             }
             name, val := part, ""
             if j := strings.Index(part, "="); j >= 0 {
                name, val = name[:j], name[j+1:]
             }
             if !isCOOKIENameValid(name) {
                continue
             }
             if filter != "" && filter != name {
                continue
             }
             val, ok := parseCOOKIEValue(val, true)
             if !ok {
                continue
             }
             COOKIEs = append(COOKIEs, &COOKIE{Name: name, Value: val})
          }
       }
       return COOKIEs
    }

总结

  1. 胆大心细
    • 升级这种操作有时候是必然要做的,新版会有更多的新特性,带来更好的性能,情况合适的话,需要大胆去做
    • 一定要让测试同学,将各个终端,各种状态,各种流程过一遍
    • 上线之后,需要继续观察
  2. 遇到问题,需要不断追查,这是一个自我成长和提升的过程
  3. 小的方面也需要完美,否则会导致很大的代价。客户端写COOKIE的方法虽然没错,但也不是很标准,当时写的时候也没在意。目前老的版本已经无法修复,如果想升级1.13,要么修复golang里的问题,要么在项目里添加处理COOKIE的逻辑,处理起来都有些麻烦

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

Golang源码COOKIE BUG追查


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 我们


推荐阅读
author-avatar
mobiledu2502869603
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有