Android使用NTLM over SSL失败

时间:2015-09-03 20:24:48

标签: java android ssl https ntlm

我正在尝试从我的Android应用程序中访问受SSL和NTLM保护的json webservice。当然,从浏览器我可以直接点击网址https://service.example.com/service1/,使用域/用户/密码进行身份验证,然后获取json结果。

使用JCIFS,我有NTLM工作,我可以通过HTTP访问这个Web服务(在特殊网络上的测试设备上),一切都很好。

工作代码

DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.getAuthSchemes().register("ntlm", new NTLMSchemeFactory());
NTCredentials creds = new NTCredentials("username", "password", "", "domain");
httpclient.getCredentialsProvider().setCredentials(AuthScope.ANY, creds);
HttpHost target = new HttpHost(serviceHostname, 80, "http");
HttpContext localContext = new BasicHttpContext();
HttpGet httpget = new HttpGet("/service1");
HttpResponse response = httpclient.execute(target, httpget, localContext);
HttpEntity entity = response.getEntity();
String responseString = EntityUtils.toString(entity);

NTLMSchemeFactory来自JCIFSEngine代码

因此,当切换到SSL时,我发现服务的服务器不提供中间证书(参见https://developer.android.com/training/articles/security-ssl.html#MissingCa) 因此抛出java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. 异常。

我已尝试在信任管理器中添加该特定证书,但它一直导致服务器返回500错误。所以我甚至进一步尝试允许所有使用空信任管理器的证书甚至开始使用它,这也会引发500个错误。

代码(最初来自Trusting all certificates using HttpClient over HTTPS

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 new X509Certificate[]{};
        }
    };

    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();
}
public static DefaultHttpClient getNewHttpClient() {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(null, null);

        MySSLSocketFactory 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);
}

使用原始工作代码,但用DefaultHttpClient httpclient = new DefaultHttpClient();

替换DefaultHttpClient httpclient = MySSLSocketFactory.getNewHttpClient();

如何将NTLM身份验证与错误的SSL连接相结合?

我试图让网络服务服务器的人员加入他们的中间证书,但我现在并没有抱太大希望。

1 个答案:

答案 0 :(得分:0)

因此我的问题的解决方案是在提供web服务的Web服务器上加载中间证书。 Android只是不喜欢或处理缺少的中间证书,如浏览器。