升级Https的那些事

作者: 掘墓人 | 来源:发表于2017-02-16 21:42 被阅读147次

    一、为什么升级Https

    1、苹果iOS强制开启ATS标准

    苹果宣布2017年1月1日起,所有提交到App Store 的App必须强制开启ATS安全标准(App Transport Security),所有连接必须使用Https加密。(后延期了,具体日期还没确定,详情见:https://developer.apple.com/news/?id=12212016b

    2、Http协议无法加密数据

    Http明文协议的缺陷,是导致数据泄露、数据篡改、流量劫持、钓鱼攻击等安全问题的重要原因。Http协议无法加密数据,所有通信数据都在网络中明文“裸奔”,通过网络的嗅探设备及一些技术手段,就可还原Http报文内容。

    二、证书申请

    1、货比三家

    (1)、赛门铁克

    优点:国际大厂,信誉保证
    缺点:证书价格太贵,购买售后全为英文,不方便

    (2)、沃通

    优点:价格公道,国内多家网站使用,中文网站及客服
    缺点:最便宜的证书不是沃通直接颁发

    (3)、免费SSL

    优点:免费,申请快
    缺点:不适合企业使用

    2、购买

    综合考虑,个人可以考虑申请免费SSL,企业申请沃通的SSL

    购买地址:http://www.wosign.com/price.htm

    三、服务器配置证书(基于Wildfly(Jboss))

    参考文档:http://www.cnblogs.com/maximo/p/5775627.html

    1、配置证书

    找到Wildfly的配置文件路径 wildfly9\standalone\configuration\standalone.xml,在应用域加入keystore信息,并将证书(juemuren.com.jks)复制到同目录下,如下:

    <security-realm name="ApplicationRealm">
        <authentication>
            <local default-user="$local" allowed-users="*" skip-group-loading="true"/>
            <properties path="application-users.properties" relative-to="jboss.server.config.dir"/>
        </authentication>
        <authorization>
            <properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
        </authorization>
    </security-realm>
    <!--以下为新增-->
    <security-realm name="SslRealm">
        <server-identities>
            <ssl>
                <keystore path="juemuren.com.jks" relative-to="jboss.server.config.dir" keystore-password="123456"/>
            </ssl>
        </server-identities>
    </security-realm>
    

    2、配置https监听

    打开wildfly9\standalone\configuration\standalone.xml,在应用域加入

    <subsystem xmlns="urn:jboss:domain:undertow:3.0">
        <buffer-cache name="default"/>
        <server name="default-server">
            <http-listener name="default" socket-binding="http" redirect-socket="https"/>
            <!--以下为新增-->
            <https-listener name="https" security-realm="SslRealm" socket-binding="https"/>
            
            <host name="default-host" alias="localhost">
                <location name="/" handler="welcome-content"/>
                <filter-ref name="server-header"/>
                <filter-ref name="x-powered-by-header"/>
            </host>
        </server>
        <servlet-container name="default">
            <jsp-config development="true"/>
        </servlet-container>
        <handlers>
            <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
        </handlers>
        <filters>
            <response-header name="server-header" header-name="Server" header-value="WildFly/10"/>
            <response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>
        </filters>
    </subsystem>
    

    3、设置http跳转https

    (1)、全局自动监听

    修改wildfly9/standalone/deployments/juemuren.com.war/WEB-INF\web.xml

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>juemuren.com</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
    

    (2)、JS监听

    在对应的页面html最开始添加下面的js代码:

    <script type="type/javascript">
        var url=window.location.href;
        if (url.indexOf("https")<0) {
            url=url.replace("http", "https");
            window.location.replace(url);
        };
    </script>
    

    四、APP配置(安卓端)

    参考文档:http://www.cnblogs.com/punkisnotdead/p/4788199.html

    1、Volley启用https支持

    (1)、修改Volley源码

    import android.content.Context;
    import android.content.pm.PackageInfo;
    import android.content.pm.PackageManager.NameNotFoundException;
    import android.net.http.AndroidHttpClient;
    import android.os.Build;
    import android.util.Log;
    
    import com.android.volley.Network;
    import com.android.volley.RequestQueue;
    import com.android.volley.toolbox.BasicNetwork;
    import com.android.volley.toolbox.DiskBasedCache;
    import com.android.volley.toolbox.HttpClientStack;
    import com.android.volley.toolbox.HttpStack;
    import com.android.volley.toolbox.HurlStack;
    
    import org.apache.http.client.HttpClient;
    import org.apache.http.conn.scheme.PlainSocketFactory;
    import org.apache.http.conn.scheme.Scheme;
    import org.apache.http.conn.scheme.SchemeRegistry;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
    import org.apache.http.params.BasicHttpParams;
    import org.apache.http.params.HttpParams;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.security.KeyManagementException;
    import java.security.KeyStore;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.UnrecoverableKeyException;
    import java.security.cert.Certificate;
    import java.security.cert.CertificateException;
    import java.security.cert.CertificateFactory;
    
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSocketFactory;
    import javax.net.ssl.TrustManagerFactory;
    
    public class Volley {
    
        /**
         * Default on-disk cache directory.
         */
        private static final String DEFAULT_CACHE_DIR = "volley";
        private static BasicNetwork network;
        private static RequestQueue queue;
        private Context mContext;
    
        /**
         * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it.
         *
         * @param context A {@link Context} to use for creating the cache dir.
         * @param stack   An {@link HttpStack} to use for the network, or null for default.
         * @return A started {@link RequestQueue} instance.
         */
        public static RequestQueue newRequestQueue(Context context, HttpStack stack, boolean selfSignedCertificate, int rawId) {
            File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
    
            String userAgent = "volley/0";
            try {
                String packageName = context.getPackageName();
                PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
                userAgent = packageName + "/" + info.versionCode;
            } catch (NameNotFoundException e) {
            }
    
            if (stack == null) {
                if (Build.VERSION.SDK_INT >= 9) {
                    if (selfSignedCertificate) {
                        stack = new HurlStack(null, buildSSLSocketFactory(context, rawId));
                    } else {
                        stack = new HurlStack();
                    }
                } else {
                    // Prior to Gingerbread, HttpUrlConnection was unreliable.
                    // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
                    if (selfSignedCertificate)
                        stack = new HttpClientStack(getHttpClient(context, rawId));
                    else {
                        stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
                    }
                }
            }
    
            Network network = new BasicNetwork(stack);
    
            RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
            queue.start();
    
            return queue;
        }
    
        /**
         * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it.
         *
         * @param context A {@link Context} to use for creating the cache dir.
         * @return A started {@link RequestQueue} instance.
         */
        public static RequestQueue newRequestQueue(Context context) {
            return newRequestQueue(context, null, false, 0);
        }
    
        private static SSLSocketFactory buildSSLSocketFactory(Context context, int certRawResId) {
            KeyStore keyStore = null;
            try {
                keyStore = buildKeyStore(context, certRawResId);
            } catch (KeyStoreException e) {
                e.printStackTrace();
            } catch (CertificateException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory tmf = null;
            try {
                tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
                tmf.init(keyStore);
    
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (KeyStoreException e) {
                e.printStackTrace();
            }
    
            SSLContext sslContext = null;
            try {
                sslContext = SSLContext.getInstance("TLS");
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            try {
                sslContext.init(null, tmf.getTrustManagers(), null);
            } catch (KeyManagementException e) {
                e.printStackTrace();
            }
    
            return sslContext.getSocketFactory();
    
        }
    
        private static HttpClient getHttpClient(Context context, int certRawResId) {
            KeyStore keyStore = null;
            try {
                keyStore = buildKeyStore(context, certRawResId);
            } catch (KeyStoreException e) {
                e.printStackTrace();
            } catch (CertificateException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (keyStore != null) {
            }
            org.apache.http.conn.ssl.SSLSocketFactory sslSocketFactory = null;
            try {
                sslSocketFactory = new org.apache.http.conn.ssl.SSLSocketFactory(keyStore);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (KeyManagementException e) {
                e.printStackTrace();
            } catch (KeyStoreException e) {
                e.printStackTrace();
            } catch (UnrecoverableKeyException e) {
                e.printStackTrace();
            }
    
            HttpParams params = new BasicHttpParams();
    
            SchemeRegistry schemeRegistry = new SchemeRegistry();
            schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
            schemeRegistry.register(new Scheme("https", sslSocketFactory, 443));
    
            ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
    
    
            return new DefaultHttpClient(cm, params);
        }
    
        private static KeyStore buildKeyStore(Context context, int certRawResId) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
            String keyStoreType = KeyStore.getDefaultType();
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
            keyStore.load(null, null);
    
            Certificate cert = readCert(context, certRawResId);
            keyStore.setCertificateEntry("ca", cert);
    
            return keyStore;
        }
    
        private static Certificate readCert(Context context, int certResourceID) {
            InputStream inputStream = context.getResources().openRawResource(certResourceID);
            Certificate ca = null;
    
            CertificateFactory cf = null;
            try {
                cf = CertificateFactory.getInstance("X.509");
                ca = cf.generateCertificate(inputStream);
    
            } catch (CertificateException e) {
                e.printStackTrace();
            }
            return ca;
        }
    }
    

    (2)、使用for other server的证书(juemuren.crt),将证书放在raw文件夹下,RequestQueue按下面获取

    RequestQueue mQueue= Volley.newRequestQueue(context, null, true, R.raw.juemuren);
    

    (3)、StringRequest延长超时时长

    StringRequest request=new StringRequest();
    request.setRetryPolicy(new DefaultRetryPolicy(30 * 1000, 2, 1.0f))
    

    2、兼容旧版本

    新版本的接口全换成https的,要想兼容旧版本,服务器配置http跳转https的监听可以设置为js版本的监听。

    完成以上设置之后,就可以愉快的用Https访问网站了,enjoy~

    相关文章

      网友评论

        本文标题:升级Https的那些事

        本文链接:https://www.haomeiwen.com/subject/yjghwttx.html