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的响应状态,响应头和响应内容. 生命周期 ...
随机推荐
- 一次C#和C++的实际应用性能比较(C++允许我们使用任何手段来提高效率,只要愿意做出足够的努力)
05年时,在微软的Rico Mariani做了一次实际应用的C#和C++的性能比较.事情起源于微软著名的元老Raymond Chen(在下敬仰的超级牛人)用C++写了一个英汉词典程序,来描述讲解优化C ...
- Dependency Injection 筆記 (3)
续上集.接着要来进一步了解的是 DI 的实现技术,也就是注入相依对象的方式.这里介绍的依赖注入方式,又称为「穷人的 DI」(poor man’s DI),因为这些用法都与特定 DI 工具无关,亦即不使 ...
- 浅析C#代理
delegate 是委托声明的基础,是.net 的委托的声明的关键字action 是基于delegate实现的代理 有多个参数(无限制个数)无返回值的代理 func 是基于delegate实现的代理 ...
- java-mysql(1)
用java写过不少单侧,用到的数据存储也是用xml或者直接文件,但是关于数据库这块很少用到,最近就学习了下java链接mysql数据库. 第一:创建一个测试用的数据库 Welcome to the M ...
- git实战经验(很实用)
推荐学习git很好的网站https://www.breakyizhan.com/git/216.html 以下内容,虽然编排不行,但是请认真的读下去,都是自己平时请自操作的,放心使用. 这是个人的gi ...
- 基于jsp技术的校园二手交易网站
[项目介绍]基于jsp的校园二手商品交易网站系统使用jsp技术进行开发,项目主要实现了一整套的校园二手交易逻辑, 主要功能如下(包括但不限于,只列出主要功能): 管理员模块 |-----用户管理 ...
- Python调试器-pdb的使用
[简介] pdb是python自带的一个包,为python程序提供了一种交互的源代码调试功能. [使用方法] 1. 使用命令: python -m pdb xxx.py #可以直接进入单步执行模式 2 ...
- Scala 学习之路(十一)—— 模式匹配
一.模式匹配 Scala支持模式匹配机制,可以代替swith语句.执行类型检查.以及支持析构表达式等. 1.1 更好的swith Scala不支持swith,可以使用模式匹配match...case语 ...
- ASP.NET Core on K8S学习初探(3)部署API到K8S
在上一篇<基本概念快速一览>中,我们把基本的一些概念快速地简单地不求甚解地过了一下,本篇开始我们会将ASP.NET Core WebAPI部署到K8S,从而结束初探的旅程. Section ...
- 深度探索c++对象模型 第一章
1,声明与定义. //声明式如下: extern int x; //对象式(变量式)声明 std::size_t numDigits(int number); //函数式声明 class Wid ...