我需要在来自 android native 应用程序的 https 连接上使用 cookie。 我正在使用 RestTemplate。
检查其他线程 (例如 Setting Security cookie using RestTemplate ) 我能够在 http 连接中处理 cookie:
restTemplate.setRequestFactory(new YourClientHttpRequestFactory());
YourClientHttpRequestFactory 扩展了 SimpleClientHttpRequestFactory
这在 http 上可以正常工作,但在 https 上不行。
另一方面,我能够解决 Android 信任 SSL 证书的 https 问题:
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(HttpUtils.getNewHttpClient()));
这里描述了 HttpUtils: http://www.makeurownrules.com/secure-rest-web-service-mobile-application-android.html
我的问题是我需要使用 ClientHttpRequestFactory 的单个实现。 所以我有3个选择:
1) 找到一种使用 SimpleClientHttpRequestFactory 处理 https 的方法
2) 找到一种使用 HttpComponentsClientHttpRequestFactory 处理 cookie 的方法
3) 使用另一种方法
最佳答案
我遇到了同样的问题。这是我的解决方案:
首先,我以与您相同的方式处理 SSL(我使用了 Bob Lee 的方法)。
Cookie 是另一回事。我过去在没有 RestTemplate 的情况下处理 cookie 的方式(即直接使用 Apache 的 HttpClient 类)是将 HttpContext 的实例传递给 HttpClient 的 execute 方法。让我们退后一步……
HttpClient有多个重载execute方法,其中之一是:
execute(HttpUriRequest request, HttpContext context)
HttpContext 的实例可以引用 CookieStore。当你创建一个 HttpContext 实例时,提供一个 CookieStore(一个新的,或者你从之前的请求中保存的):
private HttpContext createHttpContext() {
CookieStore cookieStore = (CookieStore) StaticCacheHelper.retrieveObjectFromCache(COOKIE_STORE);
if (cookieStore == null) {
Log.d(getClass().getSimpleName(), "Creating new instance of a CookieStore");
// Create a local instance of cookie store
cookieStore = new BasicCookieStore();
}
// Create local HTTP context
HttpContext localContext = new BasicHttpContext();
// Bind custom cookie store to the local context
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
return localContext;
}
当然,如果您愿意,您可以在发送请求之前将 cookie 添加到 CookieStore 的实例中。现在当你调用 execute 方法时,使用 HttpContext 的那个实例:
HttpResponse response = httpClient.execute(httpRequester, localContext);
(其中 httpRequester 是 HttpPost、HttpGet 等的实例)
如果您需要在后续请求中重新发送任何 cookie,请确保将 cookie 存储在某处:
StaticCacheHelper.storeObjectInCache(COOKIE_STORE, localContext.getAttribute(ClientContext.COOKIE_STORE), MAX_MILLISECONDS_TO_LIVE_IN_CACHE);
这段代码中使用的StaticCacheHelper类只是一个自定义类,可以将数据存储在静态Map中:
public class StaticCacheHelper {
private static final int TIME_TO_LIVE = 43200000; // 12 hours
private static Map<String, Element> cacheMap = new HashMap<String, Element>();
/**
* Retrieves an item from the cache. If found, the method compares
* the object's expiration date to the current time and only returns
* the object if the expiration date has not passed.
*
* @param cacheKey
* @return
*/
public static Object retrieveObjectFromCache(String cacheKey) {
Element e = cacheMap.get(cacheKey);
Object o = null;
if (e != null) {
Date now = new Date();
if (e.getExpirationDate().after(now)) {
o = e.getObject();
} else {
removeCacheItem(cacheKey);
}
}
return o;
}
/**
* Stores an object in the cache, wrapped by an Element object.
* The Element object has an expiration date, which will be set to
* now + this class' TIME_TO_LIVE setting.
*
* @param cacheKey
* @param object
*/
public static void storeObjectInCache(String cacheKey, Object object) {
Date expirationDate = new Date(System.currentTimeMillis() + TIME_TO_LIVE);
Element e = new Element(object, expirationDate);
cacheMap.put(cacheKey, e);
}
/**
* Stores an object in the cache, wrapped by an Element object.
* The Element object has an expiration date, which will be set to
* now + the timeToLiveInMilliseconds value that is passed into the method.
*
* @param cacheKey
* @param object
* @param timeToLiveInMilliseconds
*/
public static void storeObjectInCache(String cacheKey, Object object, int timeToLiveInMilliseconds) {
Date expirationDate = new Date(System.currentTimeMillis() + timeToLiveInMilliseconds);
Element e = new Element(object, expirationDate);
cacheMap.put(cacheKey, e);
}
public static void removeCacheItem(String cacheKey) {
cacheMap.remove(cacheKey);
}
public static void clearCache() {
cacheMap.clear();
}
static class Element {
private Object object;
private Date expirationDate;
/**
* @param object
* @param key
* @param expirationDate
*/
private Element(Object object, Date expirationDate) {
super();
this.object = object;
this.expirationDate = expirationDate;
}
/**
* @return the object
*/
public Object getObject() {
return object;
}
/**
* @param object the object to set
*/
public void setObject(Object object) {
this.object = object;
}
/**
* @return the expirationDate
*/
public Date getExpirationDate() {
return expirationDate;
}
/**
* @param expirationDate the expirationDate to set
*/
public void setExpirationDate(Date expirationDate) {
this.expirationDate = expirationDate;
}
}
}
但是!!!!截至 01/2012 Spring Android 中的 RestTemplate 不允许您将 HttpContext 添加到请求的执行中!这在 Spring Framework 3.1.0.RELEASE 中得到了修复,修复是 scheduled to be migrated into Spring Android 1.0.0.RC1 .
所以,当我们获得 Spring Android 1.0.0.RC1 时,我们应该能够添加上面示例中描述的上下文。在此之前,我们必须使用 ClientHttpRequestInterceptor 从请求/响应 header 中添加/拉取 cookie。
public class MyClientHttpRequestInterceptor implements
ClientHttpRequestInterceptor {
private static final String SET_COOKIE = "set-cookie";
private static final String COOKIE = "cookie";
private static final String COOKIE_STORE = "cookieStore";
/* (non-Javadoc)
* @see org.springframework.http.client.ClientHttpRequestInterceptor#intercept(org.springframework.http.HttpRequest, byte[], org.springframework.http.client.ClientHttpRequestExecution)
*/
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] byteArray,
ClientHttpRequestExecution execution) throws IOException {
Log.d(getClass().getSimpleName(), ">>> entering intercept");
List<String> cookies = request.getHeaders().get(COOKIE);
// if the header doesn't exist, add any existing, saved cookies
if (cookies == null) {
List<String> cookieStore = (List<String>) StaticCacheHelper.retrieveObjectFromCache(COOKIE_STORE);
// if we have stored cookies, add them to the headers
if (cookieStore != null) {
for (String cookie : cookieStore) {
request.getHeaders().add(COOKIE, cookie);
}
}
}
// execute the request
ClientHttpResponse response = execution.execute(request, byteArray);
// pull any cookies off and store them
cookies = response.getHeaders().get(SET_COOKIE);
if (cookies != null) {
for (String cookie : cookies) {
Log.d(getClass().getSimpleName(), ">>> response cookie = " + cookie);
}
StaticCacheHelper.storeObjectInCache(COOKIE_STORE, cookies);
}
Log.d(getClass().getSimpleName(), ">>> leaving intercept");
return response;
}
}
拦截器拦截请求,在缓存中查看是否有任何 cookie 添加到请求中,然后执行请求,然后从响应中提取任何 cookie 并存储它们以供将来使用。
在请求模板中添加拦截器:
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(HttpClientHelper.createDefaultHttpClient(GET_SERVICE_URL)));
ClientHttpRequestInterceptor[] interceptors = {new MyClientHttpRequestInterceptor()};
restTemplate.setInterceptors(interceptors);
你去吧!我已经测试过了,它可以工作。这应该会让你一直坚持到 Spring Android 1.0.0.RC1,那时我们可以直接将 HttpContext 与 RestTemplate 一起使用。
希望这对其他人有所帮助!
关于android - Spring 安卓: using RestTemplate with https and cookies,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7101677/
我正在使用Ruby2.1.1和Rails4.1.0.rc1。当执行railsc时,它被锁定了。使用Ctrl-C停止,我得到以下错误日志:~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`gets':Interruptfrom~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`verify_server_version'from~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.
最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路
转自:spring.profiles.active和spring.profiles.include的使用及区别说明下文笔者讲述spring.profiles.active和spring.profiles.include的区别简介说明,如下所示我们都知道,在日常开发中,开发|测试|生产环境都拥有不同的配置信息如:jdbc地址、ip、端口等此时为了避免每次都修改全部信息,我们则可以采用以上的属性处理此类异常spring.profiles.active属性例:配置文件,可使用以下方式定义application-${profile}.properties开发环境配置文件:application-dev
我无法运行Spring。这是错误日志。myid-no-MacBook-Pro:myid$spring/Users/myid/.rbenv/versions/1.9.3-p484/lib/ruby/gems/1.9.1/gems/spring-0.0.10/lib/spring/sid.rb:17:in`fiddle_func':uninitializedconstantSpring::SID::DL(NameError)from/Users/myid/.rbenv/versions/1.9.3-p484/lib/ruby/gems/1.9.1/gems/spring-0.0.10/li
目录SpringBootStarter是什么?以前传统的做法使用SpringBootStarter之后starter的理念:starter的实现: 创建SpringBootStarter步骤在idea新建一个starter项目、直接执行下一步即可生成项目。 在xml中加入如下配置文件:创建proterties类来保存配置信息创建业务类:创建AutoConfiguration测试如下:SpringBootStarter是什么? SpringBootStarter是在SpringBoot组件中被提出来的一种概念、简化了很多烦琐的配置、通过引入各种SpringBootStarter包可以快速搭建出一
文章目录前言一、Elasticsearch版本介绍二、客户端种类三、客户端与版本兼容性四、引入Elasticsearch依赖包五、客户端配置六、Elasticsearch使用前言ElasticSearch是Elastic公司出品的一款功能强大的搜索引擎,被广泛的应用于各大IT公司,它的代码位于https://github.com/elastic/elasticsearch,目前是一个开源项目。ElasticSearch公司的另外两个开源产品Logstash、Kibana与ElasticSearch构成了著名的ELK技术栈。。他们三个共同形成了一个强大的生态圈。简单地说,Logstash负责数据
有道无术,术尚可求,有术无道,止于术。本系列SpringBoot版本3.0.4本系列SpringSecurity版本6.0.2本系列SpringAuthorizationServer版本1.0.2源码地址:https://gitee.com/pearl-organization/study-spring-security-demo文章目录前言1.OAuth2AuthorizationServerMetadataEndpointFilter2.OAuth2AuthorizationEndpointFilter3.OidcProviderConfigurationEndpointFilter4.N
如何用IDEA2022创建并初始化一个SpringBoot项目?目录如何用IDEA2022创建并初始化一个SpringBoot项目?0. 环境说明1. 创建SpringBoot项目 2.编写初始化代码0. 环境说明IDEA2022.3.1JDK1.8SpringBoot1. 创建SpringBoot项目 打开IDEA,选择NewProject创建项目。 填写项目名称、项目构建方式、jdk版本,按需要修改项目文件路径等信息。 选择springboot版本以及需要的包,此处只选择了springweb。 此处需特别注意,若你使用的是jdk1
我今天遇到了同样的问题,有一个建议:在您的命令前添加bundleexec可能会解决此问题。前置bundleexec没有帮助(我已经这样做了)。springstop和springrestart没有帮助。我需要做的:bundleupdatespring这对我有用。在之前的gemlock文件中使用spring版本是否有更好的解决方案? 最佳答案 我删除gemfile.lock并运行bundle通常会清除一切。否则只需从Gemfile中删除gem"spring"并运行bundle 关于ruby-
前言微信支付是企业级项目中经常使用到的功能,作为后端开发人员,完整地掌握该技术是十分有必要的。一、申请流程和步骤图1-1注册微信支付账号获取微信小程序APPID获取微信商家的商户ID获取微信商家的API私钥配置微信支付回调地址绑定微信小程序和微信支付的关系搭建SpringBoot工程编写后台支付接口发布部署接口服务项目使用微信小程序或者UniAPP调用微信支付功能支付接口的封装配置jwt或者openid的token派发原生微信小程序完成支付对接二、注册商家2.1商户平台商家或者企业想要通过微信支付来进行商品的销售,必须先通过微信平台(pay.weixin.qq.com)去将商家进行注册。注册成