有人决定使用Sharepoint建立一个公共网站。该网站仅供参考,不使用任何Sharepoint文档库或协作功能。该网站面向公众,无需登录即可使用SSL。
从计算机浏览器查看时,该网站看起来不错,但在Android Chrome上查看时,会提示用户安装安全证书。消息是这样的:
未找到证书
应用Chrome已申请证书。选择证书将允许应用程序现在和将来使用此身份与服务器。该应用已将请求服务器标识为,但如果您信任该应用,则应仅授予应用对该证书的访问权限。
我认为这是由于Android没有安装默认用户证书而且Sharepoint想要识别用户。无论如何重新配置Sharepoint所以它不会请求客户端证书吗?
答案 0 :(得分:0)
android developer website对此有很多说法。特别是看似重要的段落是
未知的证书颁发机构 在这种情况下,会发生SSLHandshakeException,因为您拥有一个不受系统信任的CA.这可能是因为您拥有来自新CA的证书,该证书尚未受到Android的信任,或者您的应用程序在没有CA的旧版本上运行。更常见的是,CA不为人知,因为它不是公共CA,而是由政府,公司或教育机构等组织发布的私人CA,供自己使用。 幸运的是,您可以教HttpsURLConnection来信任一组特定的CA.该过程可能有点复杂,因此下面是一个从InputStream获取特定CA的示例,使用它创建KeyStore,然后用于创建和初始化TrustManager。 TrustManager是系统用于验证来自服务器的证书的方法,并且通过从具有一个或多个CA的KeyStore创建一个证书 - 这些CA将是该TrustManager信任的唯一CA. 给定新的TrustManager,该示例初始化一个新的SSLContext,它提供了一个SSLSocketFactory,可用于覆盖HttpsURLConnection的默认SSLSocketFactory。这样,连接将使用您的CA进行证书验证。 以下是使用华盛顿大学的组织CA的完整示例:
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// From https://www.washington.edu/itconnect/security/ca/load-der.crt
InputStream caInput = new BufferedInputStream(new FileInputStream("load- der.crt"));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
// Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = new URL("https://certs.cac.washington.edu/CAtest/");
HttpsURLConnection urlConnection =
(HttpsURLConnection)url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
copyInputStreamToOutputStream(in, System.out);
使用了解您的CA的自定义TrustManager,系统可以验证您的服务器证书是否来自受信任的颁发者。
警告:许多网站描述了一个糟糕的替代解决方案,即安装一个什么都不做的TrustManager。如果您这样做,您可能也不会加密您的通信,因为任何人都可以通过使用DNS技巧发送您的用户来攻击您的公共Wi-Fi热点用户'通过他们自己的代理流量假装成你的服务器。然后,攻击者可以记录密码和其他个人数据。这是有效的,因为攻击者可以生成证书,并且没有实际验证证书来自可信来源的TrustManager,您的应用可以与任何人交谈。所以不要这样做,甚至不是暂时的。您始终可以让您的应用程序信任服务器证书的颁发者,所以就这样做。