android https通信跟服务器配置说明

来源:互联网 发布:淘宝互刷平台 编辑:程序博客网 时间:2024/06/02 06:00

由于之前项目一直使用的是http通信的,基本上能解决项目的一些个别问题,但是一旦出现了涉及到隐私问题,或者等同于金币性质的功能了,如果此时还采用http协议通信的话,那么就会很糟糕了。之前由于这个问题,导致出现被人刷金币,耍了RMB1000多,为了预防这种情况的存在,所以想到了https协议。

之前一直没接触过这方面的东西,以为只是简单的android https通信而已,却不料,跟服务器的配置有相关的重要性!

以下只是测试阶段的流程。

首先,测试服务器是nginx搭建的ip是:192.168.0.40 然后在nginx的配置文件里


server
{
listen       80;
listen      443;


ssl on;
ssl_certificate /home/wwwroot/ssl/hao-pem.crt;
ssl_certificate_key /home/wwwroot/ssl/hao.key;


ssl_session_timeout  5m;


ssl_protocols  SSLv2 SSLv3 TLSv1;
ssl_ciphers  HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers   on;


server_name www.haojiong.com haojiong.com;
index index.html index.htm index.php;
root  /home/wwwroot/jiqun;
#rewrite ^(.*) https://192.168.0.40$1 permanent;
#error_page 404 456.txt;
location ~ .*\.(php|php5)?$
{
try_files $uri =404;
fastcgi_pass  unix:/tmp/php-cgi.sock;
fastcgi_index index.php;
include fcgi.conf;
}


location /status {
stub_status on;
access_log   off;
}


location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires      30d;
}


location ~ .*\.(js|css)?$
{
expires      12h;
}


access_log  /home/wwwlogs/access.log  access;
}


其中这两行代码是重要的

ssl_certificate /home/wwwroot/ssl/hao-pem.crt;
ssl_certificate_key /home/wwwroot/ssl/hao.key;

至于hao-pem.crt 跟hao.key这两个文件时怎么得来的,可以点此链接

点击打开链接 这里会流程性的介绍怎么得来的。

在此之前,请先用keytool生成一个keystore文件。

以上是服务器端的操作。接下来是客户端的操作流程

用之前生成keystore文件,然后转成bks文件,

这个连接有介绍怎么转转成bks。这个过程中会让你输入密码(我自己的理解就是一个密钥,这个密码是在客户端那边需要用到的)

之后android客户端代码如下



特别注意,这里我也不是搞的很懂

String URL = "https://192.168.0.40/new2.php";

这里的URL弄成ip形式的话,就可以正常运行。但是如果变成域名形式的话,就会出现乱七八糟的异常

这里我也不知道怎么回事


/**请求方法*/
public void DoRequest() {
// Instantiate the custom HttpClient
DefaultHttpClient client = MyHttpClient.setContext(this);
HttpGet get = new HttpGet(URL);
// 以 GET 方式读取服务器返回的数据
HttpResponse getResponse = null;
HttpEntity responseEntity = null;
try {
getResponse = client.execute(get);
responseEntity = getResponse.getEntity();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String string =null;
try {
string = inputStream2String(responseEntity.getContent());
Log.i(key, string);
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}
/**InputStream转成String方法*/
public static String inputStream2String(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int i = -1;
while ((i = is.read()) != -1) {
baos.write(i);
}
return baos.toString();
}



MyHttpClient类:


public class MyHttpClient extends DefaultHttpClient {


private static Context context;


public static MyHttpClient setContext(Context context) {
MyHttpClient.context = context;
return new MyHttpClient();
}


//
// public MyHttpClient(HttpParams params) {
// super(params);
// }
//
// public MyHttpClient(ClientConnectionManager httpConnectionManager,
// HttpParams params) {
// super(httpConnectionManager, params);
// }
//
@Override
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));


// 用我们自己定义的 SSLSocketFactory 在 ConnectionManager 中注册一个 443 端口
registry.register(new Scheme("https", newSslSocketFactory(), 443));
return new SingleClientConnManager(getParams(), registry);
}


private SSLSocketFactory newSslSocketFactory() {
try {
// Get an instance of the Bouncy Castle KeyStore format
KeyStore trusted = KeyStore.getInstance("BKS");
// 从资源文件中读取你自己创建的那个包含证书的 keystore 文件


InputStream in = MyHttpClient.context.getResources()
.openRawResource(Cer.keyRID); // 这个参数改成你的 bks文件名
try {

//上边说到的你自己输入的密码
String pass=Cer.passwd;
// 用 keystore 的密码跟证书初始化 trusted
trusted.load(in, pass.toCharArray());
} finally {
in.close();
}
// Pass the keystore to the SSLSocketFactory. The factory is
// responsible
// for the verification of the server certificate.
SSLSocketFactoryEx sf = new SSLSocketFactoryEx(trusted);
// Hostname verification from certificate
// http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER); // 这个参数可以根据需要调整,
return sf;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}





SSLSocketFactoryEx 类

public class SSLSocketFactoryEx extends SSLSocketFactory {      
    
    SSLContext sslContext = SSLContext.getInstance("SSL");      
      
    
    
    
    public SSLSocketFactoryEx(KeyStore truststore)      
            throws NoSuchAlgorithmException, KeyManagementException,      
            KeyStoreException, UnrecoverableKeyException {      
        super(truststore);      
      
//        TrustManager tm = new X509TrustManager() {      
//      
//            public java.security.cert.X509Certificate[] getAcceptedIssuers() {      
//                return null;      
//            }      
//      
//            @Override      
//            public void checkClientTrusted(      
//                    java.security.cert.X509Certificate[] chain, String authType)      
//                    throws java.security.cert.CertificateException {      
//      
//            }      
//      
//            @Override      
//            public void checkServerTrusted(      
//                    java.security.cert.X509Certificate[] chain, String authType)      
//                    throws java.security.cert.CertificateException {      
//      
//            }      
//        };      
        TrustManager tm = new MyX509TrustManager();
        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();      
    }   




-------------------------到此结束----------------------------------


步骤:

1:先使用keytool生成keystore文件


2:将keystore变成crt文件

keytool -export -alias mykey -keystore keystore -file yidont.crt

3:将keystore变成*-pkcs8.key文件

java ExportPriv <keystore> <alias> <password> > exported-pkcs8.key


4:把2 3中生成的crt key文件放到服务器上,使用openssl

openssl x509 -out yidont-pem.crt -outform pem -text -in yidont.crt -inform der

openssl pkcs8 -inform PEM -nocrypt -in exported-pkcs8.key -out exported.key


5:将2中的crt转成客户端(手机)可识别的bks格式

注:记得先配这个   security.provider.11=org.bouncycastle.jce.provider.BouncyCastleProvider  jdk_home\jre\lib\security\ java.security 

keytool -exportcert -alias test -file test.cert -keystore test.jks  

keytool -importcert -keystore test.bks -file test.cert -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider

 






这样的话,就算被人模拟请求了。也需要bks文件,其实bks文件我是理解成公钥,不知道对不对

就算被人反编译apk了,拿到了bks了(因为公钥本身就是要给其他人的),还需要一个密码,就是上边

所提到的一个密码。


0 0