一、为什么升级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
三、服务器配置证书(基于Wildfly(Jboss))
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配置(安卓端)
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~
本文由 掘墓人 创作,采用 CC BY-NC-ND 4.0 DEED
,转载或翻译请注明出处。
最后编辑时间为: 2019年02月3日