restTemplate重定向问题 &cookie问题
最近在做一个转发功能,zuul + ribbon + resttemplate 进行路由、负载、转发的功能
基本准备就绪,在微信自动登陆那遇到了一个坑,ribbon 系统用resttemplate 转发A系统的资源,在微信自动登陆的地方,A系统重定向到微信的地址,类似下面的代码
redirect:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx3290f3d5****&redirect_uri=http://***.com/weixin/wxAuthRedirect?redirectUrl=http%3A%2F%2F192.168.10.116%3A8081%2Finternal%2Fpage%2Fuser%2Flogin_wx&response_type=code&scope=snsapi_userinfo&state=state#wechat_redirect
结果resttemplate 自动重定向到本地的地址,如下所示:
http://192.168.10.116:**/connect/oauth2/authorize**
仔细思考了下,大概就是resttemplate 的重定向问题,查了查资料,找到一个类HttpComponentsClientHttpRequestFactory,RestTemplate初始化提供了这个类的参数
/**
* Create a new instance of the {@link RestTemplate} based on the given {@link ClientHttpRequestFactory}.
* @param requestFactory HTTP request factory to use
* @see org.springframework.http.client.SimpleClientHttpRequestFactory
* @see org.springframework.http.client.HttpComponentsClientHttpRequestFactory
*/
public RestTemplate(ClientHttpRequestFactory requestFactory) {
this();
setRequestFactory(requestFactory);
}
HttpComponentsClientHttpRequestFactory继承自ClientHttpRequestFactory,这个类的子类有HttpComponentsClientHttpRequestFactory和SimpleClientHttpRequestFactory
找到SimpleClientHttpRequestFactory,有如下方法:
第一种方式:
/**
* Template method for preparing the given {@link HttpURLConnection}.
* <p>The default implementation prepares the connection for input and output, and sets the HTTP method.
* @param connection the connection to prepare
* @param httpMethod the HTTP request method ({@code GET}, {@code POST}, etc.)
* @throws IOException in case of I/O errors
*/
protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
if (this.connectTimeout >= 0) {
connection.setConnectTimeout(this.connectTimeout);
}
if (this.readTimeout >= 0) {
connection.setReadTimeout(this.readTimeout);
} connection.setDoInput(true); if ("GET".equals(httpMethod)) {
connection.setInstanceFollowRedirects(true);
}
else {
connection.setInstanceFollowRedirects(false);
} if ("POST".equals(httpMethod) || "PUT".equals(httpMethod) ||
"PATCH".equals(httpMethod) || "DELETE".equals(httpMethod)) {
connection.setDoOutput(true);
}
else {
connection.setDoOutput(false);
} connection.setRequestMethod(httpMethod);
}
可以看到setInstanceFollowRedirects,get请求是可以重定向的,其他方法禁止了重定向,于是建个SimpleClientHttpRequestFactory的子类,禁用重定向。
于是乎 NoRedirectClientHttpRequestFactory.java
import java.io.IOException;
import java.net.HttpURLConnection; import org.springframework.http.client.SimpleClientHttpRequestFactory; public class NoRedirectClientHttpRequestFactory extends SimpleClientHttpRequestFactory { @Override
protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
// TODO Auto-generated method stub
super.prepareConnection(connection, httpMethod);
// 禁止自动重定向
connection.setFollowRedirects(false);
}
}
NoRedirectClientHttpRequestFactory httpRequestFactory = new NoRedirectClientHttpRequestFactory();
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
接着,似乎更换ClientHttpRequestFactory并不合心意,还是要使用HttpComponentsClientHttpRequestFactory来实现,HttpComponentsClientHttpRequestFactory是可以自定义HttpClient的,于是查到了HttpClient头上,HttpClient是可以设置Redirect的,
第二种方式:
HttpClient httpClient = HttpClientBuilder.create()
.setRedirectStrategy(new LaxRedirectStrategy())
.build();
httpRequestFactory.setHttpClient(httpClient);
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
默认提供了两个类,DefaultRedirectStrategy和LaxRedirectStrategy,LaxRedirectStrategy继承自DefaultRedirectStrategy
DefaultRedirectStrategy.java
/**
* Redirectable methods.
*/
private static final String[] REDIRECT_METHODS = new String[] {
HttpGet.METHOD_NAME,
HttpHead.METHOD_NAME
};
LaxRedirectStrategy.java
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/ package org.apache.http.impl.client; import org.apache.http.annotation.Contract;
import org.apache.http.annotation.ThreadingBehavior;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPost; /**
* Lax {@link org.apache.http.client.RedirectStrategy} implementation
* that automatically redirects all HEAD, GET, POST, and DELETE requests.
* This strategy relaxes restrictions on automatic redirection of
* POST methods imposed by the HTTP specification.
*
* @since 4.2
*/
@Contract(threading = ThreadingBehavior.IMMUTABLE)
public class LaxRedirectStrategy extends DefaultRedirectStrategy { public static final LaxRedirectStrategy INSTANCE = new LaxRedirectStrategy(); /**
* Redirectable methods.
*/
private static final String[] REDIRECT_METHODS = new String[] {
HttpGet.METHOD_NAME,
HttpPost.METHOD_NAME,
HttpHead.METHOD_NAME,
HttpDelete.METHOD_NAME
}; @Override
protected boolean isRedirectable(final String method) {
for (final String m: REDIRECT_METHODS) {
if (m.equalsIgnoreCase(method)) {
return true;
}
}
return false;
} }
这就很清晰了,copy一份LaxRedirectStrategy的代码,改写掉REDIRECT_METHODS中的定义方法,如下:
import org.apache.http.annotation.Contract;
import org.apache.http.annotation.ThreadingBehavior;
import org.apache.http.impl.client.DefaultRedirectStrategy; /**
*
* @ClassName: MyRedirectStrategy
* @Description: TODO
* @author thinklight
* @date 2018年4月20日 下午2:47:29
*
*/
@Contract(threading = ThreadingBehavior.IMMUTABLE)
public class MyRedirectStrategy extends DefaultRedirectStrategy { public static final MyRedirectStrategy INSTANCE = new MyRedirectStrategy(); /**
* Redirectable methods.
*/
private static final String[] REDIRECT_METHODS = new String[] {}; @Override
protected boolean isRedirectable(final String method) {
for (final String m: REDIRECT_METHODS) {
if (m.equalsIgnoreCase(method)) {
return true;
}
}
return false;
}
}
ribbon+微信各种重定向问题,解决了。
第三种方式:
自己蠢了,今天因为cookie的问题发现了简单的方式
HttpClient httpClient = HttpClientBuilder.create().disableCookieManagement().disableRedirectHandling().build();
完整代码如下:
@Autowired
RestTemplate restTemplate; @Bean
@LoadBalanced
RestTemplate restTemplate() {
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
// NoRedirectClientHttpRequestFactory httpRequestFactory = new NoRedirectClientHttpRequestFactory();// 此类型不能使用httpClient
httpRequestFactory.setConnectionRequestTimeout(2000);
httpRequestFactory.setConnectTimeout(10000);
httpRequestFactory.setReadTimeout(7200000);
// HttpClient httpClient = HttpClientBuilder.create()
// .setRedirectStrategy(new MyRedirectStrategy())
// .build();
HttpClient httpClient = HttpClientBuilder.create().disableCookieManagement().disableRedirectHandling().build();
httpRequestFactory.setHttpClient(httpClient);
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
logger.debug("指定字符编码为UTF-8,原编码为ISO-8859-1");
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
logger.debug("RestTemple默认能转换为application/json,转换追加text/plain类型");
restTemplate.getMessageConverters().add(new WxMappingJackson2HttpMessageConverter());
return restTemplate;
}
重定向参考:https://www.dozer.cc/2014/05/disable-resttemplate-redirect.html
cookie参考:https://stackoverflow.com/questions/10175649/resttemplate-and-cookie
https://stackoverflow.com/questions/22853321/resttemplate-client-with-cookies
restTemplate重定向问题 &cookie问题的更多相关文章
- 重定向 url cookie
想象下面两行伪代码: 1. setCookie(...);2. redirect(new_web_url); 首先设置一个Cookie,然后重定向到另外一个网址,这个网址跟当前网站的域名不同 在多数情 ...
- Flask框架 之重定向、cookie和session
一.URL重定向(redirect) @app.route("/login") def login(): # 使用url_for函数通过视图函数的名字找到url路径 url = u ...
- 测开之路四十八:Django之重定向与cookie
基础配置与上一篇一致 404错误 定义一个error页面 <!DOCTYPE html><html lang="en"><head> <m ...
- Servlet(六):Cookie
Cookie 学习:问题: HTTP 协议是没有记忆功能的,一次请求结束后,相关数据会被销毁.如果第二次的请求需要使用相同的请求数据怎么办呢?难道是让用户再次请求书写吗?解决: 使用 Cookie 技 ...
- 会话跟踪之Cookie
一:简介 Cookie主要用来存储用户信息,追踪用户会话.web客户端访问服务端直接采用的协议是Http,Http协议是一种无状态协议,无状态表现在不能够保留用户访问状态,无法记录用户信息.每一次的请 ...
- 关于Http请求Cookie问题
在Http请求中,很多时候我们要设置Cookie和获取返回的Cookie,在这个问题上踩了一个很大的坑,主要是两个问题: 1.不能获取到重定向返回的Cookie: 2.两次请求返回的Cookie是相同 ...
- Python3使用request/urllib库重定向问题
禁止自动重定向 python3的urllib.request模块发http请求的时候,如果服务器响应30x会自动跟随重定向,返回的结果是重定向后的最终结果而不是30x的响应结果. request是靠H ...
- .net core 1.0 中的asp.net identity 基本使用(一)
1.修改密码强度:打开Startup.cs,在public class Startup{}内找public void ConfigureServices(IServiceCollection serv ...
- JavaWeb基础:Servlet Response
ServletResponse简介 ServletResponse代表浏览器输出,它提供所有HttpResponse的设置接口,可以设置HttpResponse的响应状态,响应头和响应内容. 生命周期 ...
随机推荐
- Windows 10 (IIS 10)安装Microsoft Web Farm Framework Version 2.2 for IIS7问题
But I got an error message "iis version 7.0 or greater is required to install Web Farm Framewor ...
- QSocket 总体设计框架说明(观赏)
QSocket 是 QDAC 开源组件的一个重要的组成部分,终于要开始开工了,为了方便大家了解 QSocket,对 QSocket 的总体设计的一些想法,我在这里给大家简要的描述一下. 首先,QSoc ...
- C++迭代器 iterator
1. 迭代器(iterator)是一中检查容器内元素并遍历元素的数据类型.(1) 每种容器类型都定义了自己的迭代器类型,如vector:vector<int>::iterator iter ...
- WPF与WinForm的抉择
微软曾经对WPF(代号Avalon)抱很大的期望——新一代的华丽用户界面平台,一统Web应用和桌面应用,Flash杀手,尽管微软口头上不承认.几年下来,WPF确实实现了当初的预期的大部分功能,但离称霸 ...
- jconsole远程监控logstash agent
在logstash的jvm.options文件末尾添加: -Dcom.sun.management.jmxremote.port=9999 //指定jmx端口-Dcom.sun.managemen ...
- 关于客户端javascript的理解及事件浅析
1,核心JavaScript和客服端JavaScript都有一个单线程执行模型.脚本和事件处理程序在同一时间只能执行一个,没有并发性.这样保持了js编程的简单性. 2,document的定义:一些呈现 ...
- asp.net mvc+jquery easyui开发实战教程之网站后台管理系统开发2-Model层建立
上篇(asp.net mvc+jquery easyui开发实战教程之网站后台管理系统开发1-准备工作)文章讲解了开发过程中的准备工作,主要创建了项目数据库及项目,本文主要讲解项目M层的实现,M层这里 ...
- mpvue 开发小程序接口数据统一管理
mpvue项目里做API与数据分离统一管理 小程序里请求数据接口使用wx:request,因为考虑项目比较大,最好把wx:request封装起来,统一使用管理 utils.js 配置开发环境和线上环境 ...
- Protobuf 小试牛刀
本文以PHP为例. 环境: CentOS 6.8 proto 3.8 PHP 7.1.12 PHP protobuf扩展 3.8.0 go1.12.5 linux/amd64 本文示例仓库地址: ht ...
- java基础知识总结(二)
Java中的代码块 java中的代码块是用{}括起来的代码,进行一些功能的限定 静态代码块:在类第一次被初始化的是后执行,负责一些类的初始化操作,仅仅只执行一次 构造代码块:顾名思义,辅助构造器进行初 ...