记一次线上服务器301异常 httpclient的坑
一、场景复现
营运车应用在登录过程中需要调用用户中心认证的接口来完成统一登录,因为云服务器升级对请求限制https only,在登录过程中出现系统异常(server error服务器异常,status 500)
二、问题排查
通过kibana追踪日志发现是请求过程中,通过httpclient调用的接口地址是http开头响应码301后没有被重定向到https,由nginx接收转发到应用部署的服务器上,导致调用用户中心认证接口响应异常
<html> <head><title>301 Moved Permanently</title></head> <body bgcolor="white"> <center><h1>301 Moved Permanently</h1></center> <hr><center>BLB/22.06.1.1</center> </body> </html>
三、原因分析
Q1——httpclient不支持响应码301/302/307时对post的重定向
线上服务器因安全问题统一将网站从http升级到https,由云服务器通过负载均衡(blb)访问nginx,项目在sever to sever端是通过Apache HttpClient发送请求,因为项目A在调用项目B接口时的配置类中对项目B的应用地址配置没改成https,请求会先打到http然后返回301,理想情况下当301时httpclient要通过获取location中的新地址重新请求对应的https接口地址,再正确响应。但是使用httpClient进行POST请求调用时,httpClient的默认配置中对可重定向方法只包括GET/HEAD,因此httpclient对301处理时如果请求方法不是GET/HEAD时不会重定向。
org.apache.http.impl.client.DefaultRedirectStrategy
/** * @since 4.2 */ protected boolean isRedirectable(final String method) { for (final String m: REDIRECT_METHODS) { if (m.equalsIgnoreCase(method)) { return true; } } return false; }
@Override
public boolean isRedirected(
final HttpRequest request,
final HttpResponse response,
final HttpContext context) throws ProtocolException {
Args.notNull(request, "HTTP request");
Args.notNull(response, "HTTP response");
final int statusCode = response.getStatusLine().getStatusCode();
final String method = request.getRequestLine().getMethod();
final Header locationHeader = response.getFirstHeader("location");
switch (statusCode) {
case HttpStatus.SC_MOVED_TEMPORARILY: //302
return isRedirectable(method) && locationHeader != null;
case HttpStatus.SC_MOVED_PERMANENTLY: //301
case HttpStatus.SC_TEMPORARY_REDIRECT: //307
return isRedirectable(method);
case HttpStatus.SC_SEE_OTHER: //303
return true;
default:
return false;
} //end of switch
}
Q2——使用DefaultRedirectStrategy(未重写getRedirect方法)支持301 post重定向时,会变成get请求
org.apache.http.impl.client.DefaultRedirectStrategy
@Override public HttpUriRequest getRedirect( final HttpRequest request, final HttpResponse response, final HttpContext context) throws ProtocolException { final URI uri = getLocationURI(request, response, context); final String method = request.getRequestLine().getMethod(); if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)) { return new HttpHead(uri); } else if (method.equalsIgnoreCase(HttpGet.METHOD_NAME)) { return new HttpGet(uri); } else { final int status = response.getStatusLine().getStatusCode(); if (status == HttpStatus.SC_TEMPORARY_REDIRECT) { return RequestBuilder.copy(request).setUri(uri).build(); } else { return new HttpGet(uri); } } }
A:继承 DefaultRedirectStrategy类,重写isRedirectable和getRedirect方法
1 @Override 2 protected boolean isRedirectable(final String method) { 3 for (final String m : REDIRECT_METHODS) { 4 if (m.equalsIgnoreCase(method)) { 5 return true; 6 } 7 } 8 return false; 9 } 10 11 @Override 12 public HttpUriRequest getRedirect(HttpRequest request, HttpResponse response, HttpContext context) 13 throws ProtocolException { 14 final URI uri = getLocationURI(request, response, context); 15 final String method = request.getRequestLine().getMethod(); 16 if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)) { 17 return new HttpHead(uri); 18 } else if (method.equalsIgnoreCase(HttpGet.METHOD_NAME)) { 19 return new HttpGet(uri); 20 } else { 21 final int status = response.getStatusLine().getStatusCode(); 22 if (status == HttpStatus.SC_TEMPORARY_REDIRECT || status == HttpStatus.SC_MOVED_PERMANENTLY) { 23 return RequestBuilder.copy(request).setUri(uri).build(); 24 } else { 25 return new HttpGet(uri); 26 } 27 } 28 }
转载请注明出处:http://www.sdxiangshi.com/article/20230401/727788.html
随机推荐
-
记一次成功的sql注入入侵检测附带sql性能优化
但是如果是让你接手一个二等残废的网站,并让你在上面改版,而且不能推翻式改版,只能逐步替换旧的程序,那么你会非常痛苦,例如我遇到的问题: 问题1. 老板对你说,以前刚做完网站好好了,没有出现木马,怎么你来了,就会出现木马,先别说了,赶紧解决...
-
记一次线上数据库删除百万级数据
背景 不知道有没有读者经历过删除线上数据库记录,反正这事对我来说是挺有压力的。激动的心,颤抖的手,万一删错了数据就麻烦了,影响数量大,领导会批评,还有复盘自己批评,想想就头大。那么就要在删除数据之前做好计划,避免删数据时发生意料之外的事...
-
记一次线上商城系统高并发的优化
对于线上系统调优,它本身是个技术活,不仅需要很强的技术实战能力,很强的问题定位,问题识别,问题排查能力,还需要很丰富的调优能力。 本篇文章从实战角度,从问题识别,问题定位,问题分析,提出解决方案,实施解决方案,监控调优后的解决方案...
-
记一次线上问题 → 事务去哪了
开心一刻 小羊:哎呀,前面有奶喝 狗妈:这谁呀,走开 小羊:我就喝点,能怎么的嘛 狗妈:你喝就喝,咋还上头了呢? 小羊:真香! 狗妈:这羊犊子,真硬核! 问题背景 一天早上,楼主兴致勃勃的逛着园子的时候,右下...
-
记一次Linux服务器上查杀木马经历
开篇前言 Linux服务器一直给我们的印象是安全、稳定、可靠,性能卓越。由于一来Linux本身的安全机制,Linux上的病毒、木马较少,二则由于宣称Linux是最安全的操作系统,导致很多人对Linux的安全性有个误解:以为它永远不会感...
-
记一次 Windows 下 Python 3 的控制台虚拟终端序列(控制台颜色输出, colorama 库)的踩坑经历
修改 2022.7.31 感谢 @DavyZhou 的评论,对文章进行了一次大修改。 2022.8.2 又踩了一次坑,再补充一下 前言 本人的电脑配置为 Windows 11 , Python 版本是 Anaconda python 3....
-
记一次docker部署RabbitMQ的坑
rabbitmq 挂载数据问题 ??近日需要用到rabbitmq,发现在挂载文件夹的时候,一直报错Permission denied错误。 touch: cannot touch '/etc/rabbitmq/rabbitmq.con...
-
记一次内存无法回收导致频繁fullgc机器假死的思路
确定挂机 络绎不绝的来不同类型的bug 当bug滚滚而来时,不要怀疑,你的发布的应用基本是不可用状态了。观察哨兵监控数据,特别是内存打到80%基本就挂机了,或者监控数据缺失也基本是挂机了。此时应当马上决断: 通知运营暂停操作(大多数是因...
-
记一次SQL优化的实战记录
目录前言1. 创建表2. 需求3. 给表插入数据4. 开始根据需求写SQL4.1 第一版4.2 第二版4.3 第三版总结前言 昨天(2022-7-22)上线了我的一个功能,测试环境数据量较小,问题不大,但是上生产之后,直接卡死了,然后就开...
-
记一次Ubuntu服务器被黑经历
起因 最近我们的一台Ubuntu阿里云服务器一直提示有肉鸡行为,提示了好几天,开始并没有关注,然后连续几天后发现应该是个大问题啊。很可能服务被侵入了!!! 寻找线索 一开始我是完全懵逼的状态的,Linux不是很熟悉,只会简单的命令,安装...