我有一个执行HttpPost的应用程序。
现在我需要在接收HttpPost的服务器接受的帖子中添加一个证书。
请问我该如何解决?
非常感谢任何建议!!!
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("https://svcs.sandbox.paypal.com/AdaptivePayments/Preapproval");
try {
httppost.addHeader("X-PAYPAL-SECURITY-USERID", "maurizio.pietrantuono_api1.db.com");
httppost.addHeader("X-PAYPAL-SECURITY-PASSWORD", "1395657583");
httppost.addHeader("X-PAYPAL-SECURITY-SIGNATURE", "A0GgTivJ6ivBB8QDTl.cZfiYK5d9AZwsFixwIUdUhJc4JXTriwpfU2zw");
httppost.addHeader("X-PAYPAL-REQUEST-DATA-FORMAT", "NV");
httppost.addHeader("X-PAYPAL-RESPONSE-DATA-FORMAT", "NV");
httppost.addHeader("X-PAYPAL-APPLICATION-ID", "APP-80W284485P519543T");
StringEntity se=new StringEntity("cancelUrl=http://your_cancel_url"+
"¤cyCode=USD"+
"&endingDate=2015-03-29T08%3A00%3A00.000Z"+
"&maxAmountPerPayment=200.00"+
"&maxNumberOfPayments=30"+
"&maxTotalAmountOfAllPayments=1500.00"+
"&pinType=NOT_REQUIRED"+
"&requestEnvelope.errorLanguage=en_US"+
"&returnUrl=http://www.google.com"+
"&startingDate=2014-04-29T07%3A00%3A00.000Z"+
"&senderEmail=mauriziop-facilitator@hotmail.it");
httppost.setEntity(se);
HttpResponse response = httpclient.execute(httppost);
答案 0 :(得分:3)
这是因为Android应用程序不接受服务器提供的安全证书。有时您可能已经看到浏览器要求允许继续说"网站的安全证书不受信任!"。同样的事情在android中产生异常。因此,您必须要求应用程序接受服务器提供的任何安全证书。这是怎么做的。 http://madurangasblogs.blogspot.com/2013/08/avoiding-javaxnetsslsslpeerunverifiedex.html
但我必须告诉你,这对于生产应用来说不是一个好习惯。这违反了获得安全证书的目的。
此外,请尝试这样的事情(您需要让套接字工厂使用此默认信任管理器):
X509TrustManager manager = null;
FileInputStream fs = null;
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
try
{
fs = new FileInputStream(System.getProperty("javax.net.ssl.trustStore"));
keyStore.load(fs, null);
}
finally
{
if (fs != null) { fs.close(); }
}
trustManagerFactory.init(keyStore);
TrustManager[] managers = trustManagerFactory.getTrustManagers();
for (TrustManager tm : managers)
{
if (tm instanceof X509TrustManager)
{
manager = (X509TrustManager) tm;
break;
}
}
来源: http://android.bigresource.com/Android-Issues-with-httppost-Authentication-challenge-is-empty-Gg4BTT7Dr.html Get the authentication from the moodle for a android application
答案 1 :(得分:1)
你可能面临像Java这样的平台上最复杂但最复杂的事情之一,因此也是Android。事实证明,没有一种直接的方法可以实现这一点,因为有很多种证书,并且没有一种方法可以对所有证书进行HTTP调用,因为其中一些可能是由未知的CA签署的,其他的为了使证书有效等,需要中间捆绑
可能有一种方法可以帮助您将证书存储到用户的密钥库中,这样您就可以发出HTTPS请求,因为他们已经信任目标SSL证书。在这种情况下,您将创建一个新的KeyStore
,导入证书,然后发出HTTPS请求:
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
// Some of these exist in more than one package, be careful to include these
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
// This would reference to your KeyStore to store the certificate
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null); // This will make a new store
// In the next line, specify the file path
// You can also export the destination certificate (in your case, Paypal's)
// put it as a hardcoded `String` and work with it.
InputStream is = ...;
BufferedInputStream bis = new BufferedInputStream(is);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
while (bis.available() > 0) {
Certificate cert = cf.generateCertificate(bis);
trustStore.setCertificateEntry("myAlias" + bis.available(), cert);
}
之后,向SSL服务器发出HTTP请求应该有效。
----编辑----
您不需要为网站生成证书,因为该网站已有一个。您必须导入其现有证书。我向你展示了如何做到这一点的例子,它是在Firefox和西班牙语下完成的,但我想你会用你的语言推断出关键词。
转到要导出其证书的站点。在此示例中,我正在执行Paypal
,但您可以为任何网站执行此操作。另外还要考虑一个站点可能有多个证书,这意味着,例如https://www.paypal.com
有一个,https://sandbox.paypal.com
有另一个完全不同。你需要检查一下。
在地址栏的左侧,点击显示Paypal, Inc (US)
的绿色文字(宣布该网站有SSL证书)。
你会看到这样一个屏幕:
点击More information
按钮,您会看到以下内容:
点击See certificate
(或类似)按钮,现在您将看到此屏幕:
点击列表中的Details
标签,逐个选择网站(在这种情况下,首先是VeriSign Class 3 Public Primary Certification Authority - g5
,然后是VeriSign Class 3 Extended Validation SSL CA
,最后是www.paypal.com
),然后,点击该屏幕底部的Export...
。系统会要求您导出PEM
证书。
您刚刚完成的是导出整个证书链,但现在您必须将它们全部放在一起。只需打开一个文本文件,然后按照您下载的顺序依次附加您刚刚下载的三个证书,并特别注意不包含其他空格。
这是您必须在代码中导入的证书。在我收录的代码段中,您需要将路径放到文件中,就是这样。由于您可能希望为所有客户端包含该代码,因此您可能会做两件事:
将证书作为项目的一部分导入。这将使任何运行您的应用程序的客户端都具有该证书,这样您就可以使用上面的代码而无需任何修改,但是当Paypal更改该证书时您需要小心(他们通常会在一段时间后过期并且需要被新的有效替换 - 您可以在证书的属性中看到证书的到期时间。
如上所述导出证书,将其放在公共场所(例如,Web服务器),每次用户运行您的应用程序时,下载它并验证密钥库中的证书是否与你刚读过如果它不存在,只需第一次导入它。如果它存在且不匹配,请更新它。否则,你不需要做任何事情。
答案 2 :(得分:0)
好的,您需要做的是将服务器的证书链导入您的应用程序。
首先,您必须下载整个证书链。您可以使用任何Web浏览器执行此操作。假设你有chrome:
现在,您拥有证书,必须将它们放入密钥库。我建议你使用BKS密钥库,因为它在内部得到了android的支持。
使用此命令导入密钥:(密码在此处无关紧要,因为我们只使用密钥库来存储密钥)
keytool -list -keystore“my_keystore_path / mykeystore.bks”-provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath“provider_path / bcprov-jdkxx-xxx.jar”-storetype BKS -storepass“my_password”
将密钥库添加到您的应用程序。您可以将其放入资产,甚至可以作为原始资源。 在此之后,您必须创建一个供HttpClient使用的ClientConnectionmanager。
public ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
// Register for port 443 our SSLSocketFactory with our keystore
// to the ConnectionManager
registry.register(new Scheme("https", newSslSocketFactory(), 443));
return new SingleClientConnManager(getParams(), registry);
}
public SSLSocketFactory newSslSocketFactory() {
try {
// Get an instance of the Bouncy Castle KeyStore format
KeyStore trusted = KeyStore.getInstance("BKS");
// Get the raw resource, which contains the keystore with
// your trusted certificates (root and any intermediate certs)
InputStream in = context.getResources().openRawResource(R.raw.mykeystore);
try {
// Initialize the keystore with the provided trusted certificates
// Also provide the password of the keystore
trusted.load(in, "my_password".toCharArray());
} finally {
in.close();
}
// Pass the keystore to the SSLSocketFactory. The factory is responsible
// for the verification of the server certificate.
SSLSocketFactory sf = new SSLSocketFactory(trusted);
// Hostname verification from certificate
// http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
return sf;
} catch (Exception e) {
throw new AssertionError(e);
}
}
并以这种方式使用它:
HttpClient c = new DefaultHttpClient(createClientConnectionManager(), new DefaultHttpClient().getParams());
请注意,如果您使用此ClientConnectionManager,则只接受这些站点,其整个证书路径位于密钥库中。如果要通过此ClientConnectionmanager为其建立安全连接,则必须导入其他站点的证书
以下是有关如何通过扩展DefaultHttpClient来完成此操作的详细教程,因此您不必使用该复杂的构造函数。
http://transoceanic.blogspot.hu/2011/11/android-import-ssl-certificate-and-use.html
答案 3 :(得分:0)
您需要告诉SSLSocketFactory(org.apache.http,而不是javax)关于您的密钥库,并配置您的DefaultHTTPClient以将其用于https连接。
答案 4 :(得分:-1)
所有的拳头,你把你的userId和密码放在上面的代码中,这很危险!! (改变它,如果它不是假的!)
其次请提供一些日志信息以获得更好的帮助!
PayPal证书是有效证书,这意味着您无需在申请中嵌入证书。 只是一些建议:
1-您可以使用android-async-http库,因为它非常灵活并且有很多选项。
2-我不熟悉PayPal,但你绝对应该使用PayPal REST API。