一、背景

   最近为了做微服务高可用和优化上线流程,我参与了一个微服务的改造开发。
   主要包括redis切换哨兵模式、接入高可用xxljob集群、配置和升级脚本优化。

二、问题描述

  项目改造提测后,测试发现一个依赖远程http调用的功能不可用

三、问题分析

  查看被调用方日志发现通用Token解析错误如下图
   说明调用时传入了错误的Token,查看调用方代码:
# 使用hutool工具发起远程http请求
HashMap<String, String> headers = getHeader(modelSyncGitDto);
HttpRequest request = HttpUtil.createRequest(Method.POST, url);
HttpResponse execute = request
.addHeaders(headers)
.timeout(2000)
.body(JSONUtil.toJsonStr(modelSyncGitDto))
.execute();
# 通用工具生成jwt token放入header
private HashMap<String, String> getHeader(ModelSyncGitDto modelSyncGitDto){
String userJwtToken = JwtUtils.getJwtToken(filterConfig.getAcSecret(),null,modelSyncGitDto.getComputerUserName(),modelSyncGitDto.getOsName());
HashMap<String, String> headers = new HashMap<>(200);
headers.put("Token", userJwtToken);
return headers;
}
以上调用代码无问题,继续排查被调用方解析token的代码
# 被调用方获取token
String token = CookieUtils.resolveCookie(request, tokenKey);
if (Objects.isNull(token) || token.isBlank()){
token = request.getHeader(tokenKey);
}
if (Objects.isNull(token) || token.isBlank()){
token = request.getParameter(tokenKey);
}
return token;
发现被调用方优先从cookie获取代码,未从header获取对应Token;
调用方未设置cookie,怀疑是请求后response缓存带的。增加调用方日志查看
log.info("http请求返回,cookie={}", execute.getCookies());
请求返回后在response设置了cookie,但每次请求都是createRequest,理论不会携带cookie。添加disableCookie验证一下:
# 创建request增加禁用cookie
HttpRequest request = HttpUtil.createRequest(Method.POST, url);
HttpResponse execute = request
.disableCookie()
.addHeaders(headers)
.timeout(2000)
.body(JSONUtil.toJsonStr(modelSyncGitDto))
.execute();
发布后恢复正常,说明请求携带了cookie信息。
后期查看文档hutool的HttpUtil的确有这么一个缓存cookie的问题,参考

四、梅开二度

  提交代码并告诉测试妹纸“修复好了”。测试验证的确无问题,但遭到测试妹纸的灵魂拷问:
“线上为啥没问题,这次版本不允许夹杂额外代码上线”。
  的确,还是要找到问题的原因。

4.1 配置对比

通过对比线上配置,发现被调用方的common依赖引入了
server:
servlet:
session:
# session超时时间,不能小于1分钟
timeout: 481m
# 浏览器 Cookie 中 SessionID 名称
cookie:
name: Token
path: /
tracking-modes: COOKIE
以上配置指定了cookie key为Token,且过期时间为8小时;去掉被调用方以上配置,调用方请求打印cookie如下;
无server.servlet.session配置:
说明被调用方spring security默认会将Cookie设置在当前应用所在的域下放置SESSION。

4.2 二次请求

无server.servlet.session配置:
cookie中返回了SEESION和Token,初步怀疑是缓存返回导致;

4.2 日志对比

相同代码,通过对比其他环境调用方打印的日志,方向无论有无server.servlet.session配置,返回的response都为空
说明还是代码配置问题。

4.3 终极原因

当调用方请求被调用方时,配置的ip不是localhost、127.0.0.1、节点IP时,请求调用返回的response都不会携带cookie。
HttpUtil通过配置请求ip,cookie跨域导致cookie无法保存,也无法携带。
线上httpUtl发起的请求ip为另一台服务器nginx地址,返回的response无cookie。

五、总结

以上问题原因为2个导致:
  1. 本版本hutool的HttpUtil请求缓存了上一次请求的cookie,并在下一次携带;
  2. Spring Security 默认会将Cookie设置在当前应用所在的域下,即localhost。请求方也为localhost所在节点,由于http同源策略,导致返回的response中存在cookie。
 
 

【BUG排查记】HttpUtil和SpringSecurity结合的坑的更多相关文章

  1. 记一次线上bug排查-quartz线程调度相关

    记一次线上bug排查,与各位共同探讨. 概述:使用quartz做的定时任务,正式生产环境有个任务延迟了1小时之久才触发.在这一小时里各种排查找不出问题,直到延迟时间结束了,该任务才珊珊触发.原因主要就 ...

  2. Android分组子级的不同视图布局之BUG奇遇记

    Android分组子级的不同视图布局之BUG奇遇记 最近在使用按日期分类列表,二级条目可能不一样,于是就想到了ExpandableListView. ExpandableListView的布局显示分割 ...

  3. 日常Bug排查-系统失去响应-Redis使用不当

    日常Bug排查-系统失去响应-Redis使用不当 前言 日常Bug排查系列都是一些简单Bug排查,笔者将在这里介绍一些排查Bug的简单技巧,同时顺便积累素材_. Bug现场 开发反应线上系统出现失去响 ...

  4. 日常Bug排查-消息不消费

    日常Bug排查-消息不消费 前言 日常Bug排查系列都是一些简单Bug排查,笔者将在这里介绍一些排查Bug的简单技巧,同时顺便积累素材_. Bug现场 某天下午,在笔者研究某个问题正high的时候.开 ...

  5. 日常Bug排查-抛异常不回滚

    日常Bug排查-抛异常不回滚 前言 日常Bug排查系列都是一些简单Bug排查,笔者将在这里介绍一些排查Bug的简单技巧,同时顺便积累素材_. Bug现场 最近有人反映java应用操作数据库的时候,抛异 ...

  6. 日常Bug排查-Nginx重复请求?

    日常Bug排查-Nginx重复请求? 前言 日常Bug排查系列都是一些简单Bug排查,笔者将在这里介绍一些排查Bug的简单技巧,其中不乏一些看起来很低级但很容易犯的问题. 问题现场 有一天运维突然找到 ...

  7. wordpress插件bug排查后记(记一次由于开启memecached引起的插件bug)

    这篇文章是写给自己的. 周三的时候我在维护公司的一个wordpress项目页面时发现了一个非常奇怪的情况:当我尝试更新网站上的一个页面后,在wordpress后台的编辑器中发现其内容并没有按我预期的将 ...

  8. 记一次偶发的bug排查——redis-py-cluster库的bug

     排查流水账: 通过平台监控,发现很多偶发的查看推荐列表的接口时延大于0.5s 写单元测试,不能重现.在测试环境不能重现.只有在正式环境可以偶发重现. 通过日志埋点,等待重现 不断地加日志埋点后发现耗 ...

  9. 团队项目-BUG排查-ADT工程 To Android Studio 一整天的排查日记

    4-22 10:44至4-23 0:45 ①打开Eclipse从Github上Clone MathsApp到本机,报错'Unable to resolve target'android-19' ②尝试 ...

  10. 一次压力测试Bug排查-epoll使用避坑指南

    Bug复现 使用Webbench对服务器进行压力测试,创建1000个客户端,并发访问服务器10s,正常情况下有接近8万个HTTP请求访问服务器. 结果显示仅有7个请求被成功处理,0个请求处理失败,服务 ...

随机推荐

  1. Python如何完成一个上课点名系统!

    阅读目录 一.准备工作 二.预览 三.思路 四.源代码 五.总结 一.准备工作 1.Tkinter Tkinter 是 python 内置的 TK GUI 工具集.TK 是 Tcl 语言的原生 GUI ...

  2. Linux 基础-文件及目录管理

    本文大部分内容参看 <Linux基础>一书,根据自己的工程经验和理解加以修改.拓展和优化形成了本篇博客,不适合 Linux 纯小白,适合有一定基础的开发者阅读. 一,概述 在 Linux ...

  3. DRF请求的生命周期

    作为一个工作3年左右的码农,在各种框架的摸爬滚打中,我也接触了不少前端后端的技术栈,其中DRF算是我后端日常工作中的用得最多的框架.今天就简单聊聊DRF请求的生命周期.由于篇幅原因,我在此篇文章中只是 ...

  4. DashText-快速开始

    快速开始 DashText,是向量检索服务DashVector推荐使用的稀疏向量编码器(Sparse Vector Encoder),DashText可通过BM25算法将原始文本转换为稀疏向量(Spa ...

  5. PhpStorm 中切换PHP8以上报错 VCRUNTIME140.dll 与PHP 版本不兼容

    错误原因:PhpStorm 附带了旧版本或错误版本的vcruntime140.dll 解决方法: 打开PhpStorm VCRUNTIME140 存在目录  C:\Program Files\JetB ...

  6. c++11新增内容

    记录一下c++11新特性方便以后回忆 1.nullptr (对标NULL) 2.auto ,decltype(根据表达式推断类型,表达式不执行) decltype(func()) sum = 5; / ...

  7. virsh的基本使用

    virsh基础命令 1.查看运行的虚拟机 virsh list 查看所有的虚拟机(关闭和运行的,不包括摧毁的) virsh list --all 2..启动虚拟机 virsh start 虚拟机名称 ...

  8. 使用 C# 入门深度学习:线性代数

    教程名称:使用 C# 入门深度学习 作者:痴者工良 地址: https://torch.whuanle.cn 线性代数 目录 线性代数 推荐书籍 基础知识 标量.向量.矩阵 Pytorch 的一些数学 ...

  9. (Python基础教程之十五)Python开箱Tuple–太多值无法解压

    Python示例,用于unpack元组或序列或可迭代,以便该元组可能长于N个元素,从而导致" 太多的值无法unpack "异常. 1.打开任意长度的元组 Python" ...

  10. Linux系统之Ubuntu

    常用命令: #查看安装包 dpkg -l 1)切换镜像源 本身的镜像都是国外的,下载依赖包太慢, 需要替换成国内镜像地址 国内镜像源推荐阿里 OPSX 源: https://opsx.alibaba. ...