使服务器仅接受来自Android应用程序的连接

时间:2015-04-15 20:31:45

标签: android server

我想知道是否有办法让我的托管服务只接受来自我的应用程序的连接,并拒绝来自任何网络浏览器的连接。

1 个答案:

答案 0 :(得分:2)

最好的方法可能是将SSL与客户端证书一起使用。这将为您提供身份验证和加密。

当您在线支付费用时,您可能熟悉通过HTTPS使用SSL来保护您的网络浏览器。除了必须将服务器配置为需要客户端证书之外,该过程类似。在Apache中,这是一个名为SSLVerifyClient的设置。这将强制Web服务器从客户端请求证书,然后将其验证为有效。

从Verisign等根权限分配客户端证书可能很昂贵,因此您可能希望生成自己的证书。您可以使用OpenSSL执行此操作。

获得客户端证书后,您必须将证书复制到设备上的应用程序存储中。然后,您可以使用Keystore对象打开它。一旦打开,您可以在使用HttpUrlConnection对象时将其与HTTP请求相关联。

由于您可能会生成自己的证书而不是使用来自根权限的证书,因此您需要在Android应用中设置TrustManager以接受自签名证书,并在发出请求时将其与HttpUrlConnection关联

这是一般策略,应该足以让你入门。如果您遇到某些特定问题,请尝试询问有关各个部分的个别问题。 Apache和OpenSSL部分可能会更好地发布在Server Fault

以下是服务器端内容的一些链接:
Client certificates with apache
Client-authenticated_TLS_handshake

以下是Android开发的链接:
HTTPS with Client Certificates on Android
android-ssl
FakeX509TrustManager(在开发过程中很有用)

看起来你需要的只是这些链接,但我会在这里总结一下Android代码。请注意,我没有此测试环境,因此代码不完整且未经测试。同样,这只是为了让你开始。

// open the certificate
keyStore = KeyStore.getInstance("PKCS12");
fis = new FileInputStream(certificateFile);
keyStore.load(fis, clientCertPassword.toCharArray());


// create the SSL context
KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
kmf.init(keyStore, clientCertPassword.toCharArray());
KeyManager[] keyManagers = kmf.getKeyManagers();

TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(trustStore);
TrustManager[] trustManagers = tmf.getTrustManagers();

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, trustManagers, null);


// perform the HTTP request
String result = null;
HttpURLConnection urlConnection = null;

try {
    URL requestedUrl = new URL(url);
    urlConnection = (HttpURLConnection) requestedUrl.openConnection();
    if(urlConnection instanceof HttpsURLConnection) {
        ((HttpsURLConnection)urlConnection)
             .setSSLSocketFactory(sslContext.getSocketFactory());
    }
    urlConnection.setRequestMethod("GET");
    urlConnection.setConnectTimeout(1500);
    urlConnection.setReadTimeout(1500);
    lastResponseCode = urlConnection.getResponseCode();
    result = IOUtil.readFully(urlConnection.getInputStream());
    lastContentType = urlConnection.getContentType();
} catch(Exception ex) {
    result = ex.toString();
} finally {
    if(urlConnection != null) {
        urlConnection.disconnect();
    }
}