向服务器发送HTTPS POST请求

6
这是我的HTTP JSON。
 {  
 "User": {    
    "Name": "Compulsary","Password": "Compulsary"  }
}

我需要使用HTTPS POST请求将内容发送到服务器,但我尝试发送请求时遇到了SSL服务器证书异常。如何解决这个问题?
我已经尝试使用HTTPClient和HTTPPost来发送请求,但是出现了SSL异常。我还尝试使用URLConnection并忽略SSL证书检查,但是我得到了401和405响应代码。
问题陈述:
将以上POST请求发送到服务器(请求是安全的,并接受https)。如何在Android中实现此目标?
以下是我的代码,但我得到了405错误?
// always verify the host - dont check for certificate
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
};

/**
 * Trust every server - dont check for any certificate
 */
private static void trustAllHosts() {
    // Create a trust manager that does not validate certificate chains
    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return new java.security.cert.X509Certificate[] {};
        }

        public void checkClientTrusted(X509Certificate[] chain,
                String authType) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain,
                String authType) throws CertificateException {
        }
    } };

    // Install the all-trusting trust manager
    try {
        SSLContext sc = SSLContext.getInstance("TLS");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection
                .setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private void makeRequest() {
    URL url = null;
    HttpsURLConnection urlConnection = null;
    try {
        url = new URL("https://wbapi.cloudapp.net:443/api/User/LocalLogin");
    } catch (MalformedURLException e2) {
        // TODO Auto-generated catch block
        e2.printStackTrace();
    }
    StringBuilder sb = new StringBuilder();

    try {
        trustAllHosts();
        urlConnection = (HttpsURLConnection) url.openConnection();
        urlConnection.setHostnameVerifier(DO_NOT_VERIFY);
        urlConnection.setDoOutput(true);
        urlConnection
                .setRequestProperty("Content-Type", "application/json");
        urlConnection.setFixedLengthStreamingMode(urlConnection
                .getContentLength());
    } catch (IOException e2) {
        // TODO Auto-generated catch block
        e2.printStackTrace();
    }

    try {
        urlConnection.connect();
    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    JSONObject jsonParam = new JSONObject();
    try {
        jsonParam.put("Name", "dog");
        jsonParam.put("Password", "123");
        Log.v("Length", "" + urlConnection.getContentLength());
        int HttpResult = urlConnection.getResponseCode();
        Toast.makeText(LoginActivity.this, "Response" + HttpResult,
                Toast.LENGTH_LONG).show();
        if (HttpResult == HttpsURLConnection.HTTP_OK) {
            System.out.println("ok");
            Log.v("Hi", "" + "Trex");
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    urlConnection.getInputStream(), "utf-8"));
            String line = null;
            while ((line = br.readLine()) != null) {
                sb.append(line + "\n");
            }
            br.close();

            System.out.println("" + sb.toString());
            Toast.makeText(LoginActivity.this, "" + sb.toString(),
                    Toast.LENGTH_LONG).show();

        } else {
            System.out.println("Here" + urlConnection.getResponseMessage());
        }
    } catch (MalformedURLException e) {

        e.printStackTrace();
    } catch (IOException e) {

        e.printStackTrace();
    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

日志记录条目

12-27 13:41:27.228: V/Length(3034): 72
12-27 13:41:27.248: I/System.out(3034): HereMethod Not Allowed

你应该尝试在这里查看:https://dev59.com/pG855IYBdhLWcg3wPBpx,但这并不适用于所有情况。 - neworld
1
我查看了很多stackoverflow的问题,但都没有帮助。 - Rajeev N B
如果尝试后都没有帮助,您需要大声解释您的问题并展示您的代码。 - neworld
另外,你能提供一些日志记录吗? - neworld
获取 405 响应代码 - Rajeev N B
显示剩余2条评论
2个回答

10

步骤1:创建一个名为 MySSLSocketFactory 的类,并包含以下代码:

public class MySSLSocketFactory extends SSLSocketFactory {
    SSLContext sslContext = SSLContext.getInstance("TLS");

    public MySSLSocketFactory(KeyStore truststore)
                    throws NoSuchAlgorithmException, KeyManagementException,
                    KeyStoreException, UnrecoverableKeyException {
            super(truststore);

            TrustManager tm = new X509TrustManager() {
                    public void checkClientTrusted(X509Certificate[] chain,
                                    String authType) throws CertificateException {
                    }

                    public void checkServerTrusted(X509Certificate[] chain,
                                    String authType) throws CertificateException {
                    }

                    public X509Certificate[] getAcceptedIssuers() {
                            return null;
                    }
            };

            sslContext.init(null, new TrustManager[] { tm }, null);
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port,
                    boolean autoClose) throws IOException, UnknownHostException {
            return sslContext.getSocketFactory().createSocket(socket, host, port,
                            autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
            return sslContext.getSocketFactory().createSocket();
    }

}

步骤2:创建一个名为WebClientDevWrapper的类,并包含以下代码:

public class WebClientDevWrapper {

    public static HttpClient getNewHttpClient() {
         try {
             KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
             trustStore.load(null, null);

             SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
             sf.setHostnameVerifier(
                    SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

             HttpParams params = new BasicHttpParams();
             HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
             HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

             SchemeRegistry registry = new SchemeRegistry();
             registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
             registry.register(new Scheme("https", sf, 443));

             ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

             return new DefaultHttpClient(ccm, params);
         } catch (Exception e) {
             return new DefaultHttpClient();
         }
     }

}

步骤3:在您的Activity或其他地方创建一个方法,该方法将用于进行Web调用。

/**
     * Request JSON based web service to get response
     * 
     * @param url
     *            - base URL
     * @param request
     *            - JSON request
     * @return response
     * @throws ClientProtocolException
     * @throws IOException
     * @throws IllegalStateException
     * @throws JSONException
     */
    public HttpResponse request(String url, JSONObject request)
            throws ClientProtocolException, IOException, IllegalStateException,
            JSONException {

        DefaultHttpClient client = (DefaultHttpClient) WebClientDevWrapper.getNewHttpClient();

            HttpPost post = new HttpPost(url);
            post.setEntity(new StringEntity(request.toString(), "utf-8"));
            HttpResponse response = client.execute(post);
            return response;
        }
    }

第四步:调用一个方法并获取响应。


什么是MySSLSocketFactory? - Rajeev N B
@RajeevNB 哎呀,我忘了,这是第一步。请检查。 - Paresh Mayani
我正在获取HTTPResponse对象。如何将其内容打印为字符串?还有一件事,我得到了response.getStatusLine()为500 /内部服务器错误? - Rajeev N B
@RajeevNB response.getEntity().getContent() 会返回一个 InputStream 对象,你可以在 Google 上搜索如何将这个 InputStream 对象转换成字符串。 - Paresh Mayani
难道没有更简单的解决方案吗?就像iOS默认提供的那样,或者使用一个库? - rahulg
显示剩余3条评论

0

我正在使用以下代码来实现https/http/wift/3G的组合,希望能对您有所帮助。

public class CustomHttpClient {
private static DefaultHttpClient customHttpClient;

/** A private Constructor prevents instantiation */
private CustomHttpClient() {
}

public static synchronized DefaultHttpClient getHttpClient() {
    if (customHttpClient == null) {
        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params,
                HTTP.DEFAULT_CONTENT_CHARSET);
        HttpProtocolParams.setUseExpectContinue(params, true);
        HttpProtocolParams.setUserAgent(params, "Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; Nexus One Build/FRG83) AppleWebKit/533.1(KHTML, like Gecko) Version/4.0 Mobile Safari/533.1");
        ConnManagerParams.setTimeout(params, 1000);
        HttpConnectionParams.setConnectionTimeout(params, 5000);
        HttpConnectionParams.setSoTimeout(params, 10000);
        SchemeRegistry schReg = new SchemeRegistry();
        schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
        ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params,schReg);
        customHttpClient = new DefaultHttpClient(conMgr, params);
    }
    return customHttpClient;
}

public Object clone() throws CloneNotSupportedException {
    throw new CloneNotSupportedException();
}

}

还有示例

public static String Call(String URL, List<NameValuePair> postParameters)
{
    BufferedReader in = null;
    DefaultHttpClient httpClient;
    StringBuffer sb = new StringBuffer();   
    try{
        httpClient = CustomHttpClient.getHttpClient();

        HttpProtocolParams.setUseExpectContinue(httpClient.getParams(), false); //making 3G network works*
        HttpPost request = new HttpPost(URL);
        UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(postParameters);
        request.setEntity(formEntity);
        HttpResponse response = httpClient.execute(request);
        in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
        String line = "";
        String NL = System.getProperty("line.separator");
        while ((line = in.readLine()) != null) {
        sb.append(line + NL);
        }
        in.close();

    }catch(Exception ex)
    {
        ex.printStackTrace();

    }
    return sb.toString();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接