Java HTTPS截取无效头问题

Java HTTPS截取无效头问题,java,android,ssl,openssl,ssl-certificate,Java,Android,Ssl,Openssl,Ssl Certificate,首先:如果你不知道确切的答案,那么就给我建议如何检查。谢谢 我已经尝试了很多不同的方法来实现我的截击请求的ssl,但是没有成功 我不明白我怎么会犯这个错误 ResponseJsonString= 错误的请求 错误的请求-无效的标头 HTTP错误400。请求的标头名称无效 所以一步一步地实现我的代码 这就是我截击队列的方式 mRequestQueue = Volley.newRequestQueue(this, new SslHurlStuck(SslUtils.KEYSTORE, SslUti

首先:如果你不知道确切的答案,那么就给我建议如何检查。谢谢

我已经尝试了很多不同的方法来实现我的截击请求的ssl,但是没有成功

我不明白我怎么会犯这个错误

ResponseJsonString=
错误的请求
错误的请求-无效的标头
HTTP错误400。请求的标头名称无效

所以一步一步地实现我的代码

这就是我截击队列的方式

mRequestQueue = Volley.newRequestQueue(this, new SslHurlStuck(SslUtils.KEYSTORE, SslUtils.PASSWORD_SSL, this));
这是我的
sslhurlstack

package utils.ssl;

import android.content.Context;
import android.util.Log;

import com.android.volley.toolbox.HurlStack;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;

import utils.global.AppUtils;


public class SslHurlStuck extends HurlStack
{
private final static String TAG = SslHurlStuck.class.getSimpleName();

private String mTrustStoreAssetName;
private String mTrustStorePassword;
private Context mContext;

public SslHurlStuck(final String iTrustStoreAssetName, final String iTrustStorePassword, Context iContext)
{
    super();

    mTrustStoreAssetName = iTrustStoreAssetName;
    mTrustStorePassword = iTrustStorePassword;
    mContext = iContext;
}

@Override
protected HttpURLConnection createConnection(URL url) throws IOException
{
    HttpsURLConnection urlConnection = null;

    try
    {
        urlConnection = new PinnedCertificateHttpsURLConnectionFactory(mContext).createHttpsURLConnection(url.toString(), mTrustStoreAssetName, mTrustStorePassword);
    }
    catch (Throwable iThrowable)
    {
        AppUtils.printLog(Log.ERROR, TAG, iThrowable.getMessage());
    }

    return urlConnection;
}
}
最后是我的
PinnedCertificateHttpsURLConnectionFactory

package utils.ssl;

import android.content.Context;
import android.util.Log;

import java.net.URL;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

 import javax.net.ssl.HostnameVerifier;
javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import utils.global.AppUtils;
import webServices.global.RequestStringBuilder;


public class PinnedCertificateHttpsURLConnectionFactory
{
private final static String TAG = PinnedCertificateHttpsURLConnectionFactory.class.getSimpleName();

private final Context mContext;

public PinnedCertificateHttpsURLConnectionFactory(Context iContext)
{
    mContext = iContext;
}

HttpsURLConnection createHttpsURLConnection(String urlString, final String iTrustStoreAssetName, final String iTrustStorePassword) throws Throwable
{
    // Initialize the trust manager factory instance with our trust store
    // as source of certificate authorities and trust material.
    KeyStore trustStore = new TrustStoreFactory(iTrustStoreAssetName, iTrustStorePassword, mContext).createTrustStore();
    String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm);
    trustManagerFactory.init(trustStore);

    // Initialize the SSL context.
    TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(trustManagerFactory.getTrustManagers());
    SSLContext sslContext = SSLContext.getInstance(SslUtils.PROTOCOL_TLS);
    sslContext.init(null, wrappedTrustManagers, null);

    // Create the https URL connection.
    URL url = new URL(urlString);
    HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
    urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
    urlConnection.setHostnameVerifier(getHostnameVerifier());

    return urlConnection;
}

// Let's assume your server app is hosting inside a server machine
// which has a server certificate in which "Issued to" is "localhost",for example.
// Then, inside verify method you can verify "localhost".
// If not, you can temporarily return true
private HostnameVerifier getHostnameVerifier()
{
    return new HostnameVerifier()
    {
        @Override
        public boolean verify(String hostname, SSLSession session)
        {
            HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();

            String localHost = SslUtils.SSL_LOCAL_HOST_DEV;

            if (RequestStringBuilder.isEnvironmentProd())
            {
                localHost = SslUtils.SSL_LOCAL_HOST_PROD;
            }

            return hv.verify(localHost, session);
            //              return hv.verify("localhost", session);
            //              return true;
        }
    };
}

private TrustManager[] getWrappedTrustManagers(TrustManager[] trustManagers)
{
    final X509TrustManager originalTrustManager = (X509TrustManager) trustManagers[0];

    final X509TrustManager x509TrustManager = new X509TrustManager()
    {
        public X509Certificate[] getAcceptedIssuers()
        {
            return originalTrustManager.getAcceptedIssuers();
        }

        public void checkClientTrusted(X509Certificate[] certs, String authType)
        {
            try
            {
                if (certs != null && certs.length > 0)
                {
                    for (X509Certificate cer : certs)
                    {
                        cer.checkValidity();
                    }
                }
                else
                {
                    originalTrustManager.checkClientTrusted(certs, authType);
                }
            }
            catch (CertificateException e)
            {
                AppUtils.printLog(Log.ERROR, TAG, "checkClientTrusted" + e.toString());
            }
        }

        public void checkServerTrusted(X509Certificate[] certs, String authType)
        {
            try
            {
                if (certs != null && certs.length > 0)
                {
                    for (X509Certificate cer : certs)
                    {
                        cer.checkValidity();
                    }
                }
                else
                {
                    originalTrustManager.checkServerTrusted(certs, authType);
                }
            }
            catch (CertificateException e)
            {
                AppUtils.printLog(Log.ERROR, TAG, "checkServerTrusted" + e.toString());
            }
        }
    };

    return new TrustManager[] {x509TrustManager};
}
}
最后一个
TrustStoreFactory

public class TrustStoreFactory
{
private String mTrustStoreAssetName;
private String mTrustStorePassword;

private Context mContext;

public TrustStoreFactory(final String iTrustStoreAssetName, final String iTrustStorePassword, final Context iContext)
{
    mTrustStoreAssetName = iTrustStoreAssetName;
    mTrustStorePassword = iTrustStorePassword;
    mContext = iContext;
}

KeyStore createTrustStore() throws Throwable
{
    // Retrieve the trust store file from the assets.
    InputStream inputStream = mContext.getAssets().open(mTrustStoreAssetName);

    try
    {
        // Create a key store with the retrieved input stream.
        KeyStore trustStore = KeyStore.getInstance(SslUtils.KEYSTORE_EXTENSION_BKS);

        trustStore.load(inputStream, mTrustStorePassword.toCharArray());

        return trustStore;
    }
    finally
    {
            inputStream.close();
    }
}
}
所以,问题是,我做错了什么

我的密钥库由2个cer文件组成,我尝试了不同的组合将cer添加到密钥库。。。但一切都没有改变

事实上,我不认为代码有问题,我认为证书有问题,但我不明白到底是什么问题,以及如何解决它

有趣的是,在iOS中,同样的ssl检查以另一种方式工作,我们只需要从响应中获取证书,然后在其上
getPublicKey()
,并比较响应证书中的公钥是否等于应用程序中的证书公钥。。。但在安卓系统中要困难得多


请随便问一下

,在我的情况下,我不知道为什么,但我只是删除了带有响应值的
内容类型
标题,一切正常

我的答案就在这里


通过截击,内容类型标题与其他标题的处理方式不同。特别是,重写getHeaders()以更改内容类型并不总是有效

试试这个

headers.put("Content-Type", "application/json");

您正在使用的URL是什么?