IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Android使用SSL自签名证书 -> 正文阅读

[网络协议]Android使用SSL自签名证书

fd70326dfc48dfcd48655bbee9f516f0.png

一般情况下公司都是通过CA机构来购买SSL证书,但是这种证书费用普遍比较贵,所以在debug环境下可以考虑使用自签名证书。

这篇内容将介绍Android如何使用自签名证书,主要分为以下4个步骤:

  1. 创建服务端SSL自签名证书

  2. 下载并配置 Tomcat 服务器

  3. Android端导入SSL证书

  4. 同时支持自签名证书和系统证书

4d495241a320e7908fcf91b77b3b1d28.gif

1 创建服务端SSL自签名证书

通过工具Keytool,可以使用如下命令快速生成Java服务器能够识别的jks格式证书:

keytool?-genkey?-alias?my_server?-keyalg?RSA?-keystore?my_server.jks?-validity?3600?-storepass?123456

执行以上命令后,会弹出一些咨询信息,可以根据实际情况填写或者随意填写也OK。如下所示:

What?is?your?first?and?last?name?
??[Unknown]:??Danny
What?is?the?name?of?your?organizational?unit?
??[Unknown]:??Null
What?is?the?name?of?your?organization?
??[Unknown]:??Null
What?is?the?name?of?your?City?or?Locality?
??[Unknown]:??SH
What?is?the?name?of?your?State?or?Province?
??[Unknown]:??SH
What?is?the?two-letter?country?code?for?this?unit?
??[Unknown]:??CN
Is?CN=Danny,?OU=Null,?O=Null,?L=SH,?ST=SH,?C=CN?correct?
??[no]:??yes

Enter?key?password?for?<my_server>
????(RETURN?if?same?as?keystore?password):
Re-enter?new?password:

注意最后需要输入密码123456。执行成功之后,就可以在当前目录看到一个新生成的服务端SSL证书:my_server.jks?。

b58ede3f86a1468f501024c92a86ef88.gif

2 下载并配置 Tomcat 服务器

创建好服务端使用的SSL证书之后,接下来就需要将其配置到服务端的配置项里,这里我们使用Tomcat搭建本地服务用来演示。

2.1 下载 Tomcat (Mac电脑版)

浏览器中输入Tomcat官方下载链接:

https://tomcat.apache.org/download-90.cgi

选中 core zip 包进行下载,如下图:

42c44780c599685a2cb92cc45b176d08.png

解压下载之后的zip包,并重命名为Tomcat,然后在Terminal中将其移动/Library目录,接下来进入 /Library/Tomcat/bin 目录,使用如下命令启动Tomcat服务器:

sudo?sh?startup.sh

上述命令需求admin权限,执行成功之后,就可以验证Tomcat是否成功打开。在浏览器中输入 localhost:8080,如果出现如下截图内容,则说明Tomcat启动成功。

dd145068af5567f9acecdab42f0c4953.png

2.2 Tomcat配置SSL证书

下载好Tomcat并启动成功之后,接下来就需要配置SSL证书了。进入Tomcat/conf/目录,编辑?server.xml?配置文件,在 <Service>?标签中添加如下?<Connector> 标签:

<?xml?version="1.0"?encoding="UTF-8"?>
<Server>
??<Service>
???...
????<Connector
????SSLEnabled="true"
????acceptCount="100"
????clientAuth="false"
????disableUploadTimeout="true"
????enableLookups="true"
????keystoreFile="/Users/Danny.Jiang/Desktop/certificate/android_cert/my_server.jks"
????keystorePass="123456"
????maxSpareThreads="75"
????maxThreads="200"
????minSpareThreads="5"
????port="8181"
????protocol="org.apache.coyote.http11.Http11NioProtocol"
????scheme="https"
????secure="true"
????sslProtocol="TLS"?/>
??</Service>
</Server>

添加以上配置之后,重新在浏览器中输入?https://localhost:8181/ 就会看到如下warning信息:

083bde97f346294e394bb9f9534a319e.png

看到上述warning信息,就说明服务端的SSL证书配置成功了。

b2e30e38da4a00b55108fe3c0e695efe.gif

3 Android端导入SSL证书

3.1 导出Android端SSL证书

使用如下命令,从上面创建的服务端证书server.jks中导出客户端证书:

keytool?-export?-alias?my_server?-file?my_client.cer?-keystore?my_server.jks?-storepass?123456

上述命令执行成功之后,将生成my_client.cer证书文件,这个就是Android端使用的自签名SSL证书。

3.2?将证书导入Android项目

创建Android项目SelfSignedCertificateDemo,如下

5023c078cea26daf0ca2a2d8cf3c2afd.png

为了增加对比效果,我们创建2个Button控件,分别用来获取baidu和本地Tomcat服务器的数据,如下:

<?xml?version="1.0"?encoding="utf-8"?>
<LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"
????android:layout_width="match_parent"
????android:layout_height="match_parent"
????android:orientation="vertical">

????<Button
????????android:layout_width="match_parent"
????????android:layout_height="wrap_content"
????????android:onClick="getBaidu"
????????android:text="获取baidu首页数据"?/>

????<Button
????????android:layout_width="match_parent"
????????android:layout_height="wrap_content"
????????android:onClick="getTomcat"
????????android:text="获取Tomcat服务器数据"?/>

</LinearLayout>

getBaidu和getTomcat这2个方法具体如下:

private?String?BAIDU_URL?=?"https://www.baidu.com/";
private?String?TOMCAT_URL?=?"https://192.168.1.105:8181/";
private?static?OkHttpClient?mOkHttpClient;

public?void?getBaidu(View?view)?{
????Request?request?=?new?Request.Builder()
????????????.url(BAIDU_URL)
????????????.build();
????mOkHttpClient.newCall(request).enqueue(new?Callback()?{
????????@Override
????????public?void?onFailure(Call?call,?IOException?e)?{
????????????Log.i("TAG",?"getBaidu?onFailure:?"?+?e.getMessage());
????????}

????????@Override
????????public?void?onResponse(Call?call,?Response?response)?throws?IOException?{
????????????Log.i("TAG",?"getBaidu?response:?"?+?response.body().string());
????????}
????});
}

public?void?getTomcat(View?view)?{
????Request?request?=?new?Request.Builder()
????????????.url(TOMCAT_URL)
????????????.build();
????mOkHttpClient.newCall(request).enqueue(new?Callback()?{
????????@Override
????????public?void?onFailure(Call?call,?IOException?e)?{
????????????Log.i("TAG",?"getTomcat?onFailure:?"?+?e.getMessage());
????????}

????????@Override
????????public?void?onResponse(Call?call,?Response?response)?throws?IOException?{
????????????Log.i("TAG",?"getTomcat?response:?"?+?response.body().string());
????????}
????});
}

上述代码中的TOMCAT_URL需要改为自己电脑的IP地址。默认情况下上述2个方法的执行结果如下:

getBaidu?response:?<!DOCTYPE?html>
????<!--STATUS?OK--><html>?<head><meta?http-equiv=content-type?content=text/html;charset=utf-8><meta?http-equiv=X-UA-Compatible?content=IE=Edge><meta?content=always?name=referrer><link?rel=stylesheet?type=text/css?href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head>?<body?link=#0000cc>?<div?id=wrapper>?<div?id=head>?<div?class=head_wrapper>?<div?class=s_form>?<div?class=s_form_wrapper>?<div?id=lg>?<img?hidefocus=true?src=//www.baidu.com/img/bd_logo1.png?width=270?height=129>?</div>?<form?id=form?name=f?action=//www.baidu.com/s?class=fm>?<input?type=hidden?name=bdorz_come?value=1>?<input?type=hidden?name=ie?value=utf-8>?<input?type=hidden?name=f?value=8>?<input?type=hidden?name=rsv_bp?value=1>?<input?type=hidden?name=rsv_idx?value=1>?<input?type=hidden?name=tn?value=baidu><span?class="bg?s_ipt_wr"><input?id=kw?name=wd?class=s_ipt?value?maxlength=255?autocomplete=off?autofocus=autofocus></span><span?class="bg?s_btn_wr"><input?type=submit?id=su?value=百度一下?class="bg?s_btn"?autofocus></span>?</form>?</div>?</div>?<div?id=u1>?<a?href=http://news.baidu.com?name=tj_trnews?class=mnav>新闻</a>?<a?href=https://www.hao123.com?name=tj_trhao123?class=mnav>hao123</a>?<a?href=http://map.baidu.com?name=tj_trmap?class=mnav>地图</a>?<a?href=http://v.baidu.com?name=tj_trvideo?class=mnav>视频</a>?<a?href=http://tieba.baidu.com?name=tj_trtieba?class=mnav>贴吧</a>?<noscript>?<a?href=http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1?name=tj_login?class=lb>登录</a>?</noscript>?<script>document.write('<a?href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+?encodeURIComponent(window.location.href+?(window.location.search?===?""???"?"?:?"&")+?"bdorz_come=1")+?'"?name="tj_login"?class="lb">登录</a>');
????????????????????</script>?<a?href=//www.baidu.com/more/?name=tj_briicon?class=bri?style="display:?block;">更多产品</a>?</div>?</div>?</div>?<div?id=ftCon>?<div?id=ftConw>?<p?id=lh>?<a?href=http://home.baidu.com>关于百度</a>?<a?href=http://ir.baidu.com>About?Baidu</a>?</p>?<p?id=cp>&copy;2017&nbsp;Baidu&nbsp;<a?href=http://www.baidu.com/duty/>使用百度前必读</a>&nbsp;?<a?href=http://jianyi.baidu.com/?class=cp-feedback>意见反馈</a>&nbsp;京ICP证030173号&nbsp;?<img?src=//www.baidu.com/img/gs.gif>?</p>?</div>?</div>?</div>?</body>?</html>

getTomcat?onFailure:?java.security.cert.CertPathValidatorException:?Trust?anchor?for?certification?path?not?found.

可以看出getTomcat请求报错,原因是客户端验证服务端SSL证书失败。最简单的办法就是强制客户端让不检查所有的SSL证书,做法如下:

1 创建自定义X509TrustManager和HostnameVerifier

/**
?*?创建信任所有证书的TrustManager
?*?@return
?*/
private?static?X509TrustManager?createTrustAllTrustManager()?{
????return?new?X509TrustManager()?{
????????@Override
????????public?void?checkClientTrusted(X509Certificate[]?chain,?String?authType)?throws?CertificateException?{
????????}

????????@Override
????????public?void?checkServerTrusted(X509Certificate[]?chain,?String?authType)?throws?CertificateException?{
????????}

????????@Override
????????public?X509Certificate[]?getAcceptedIssuers()?{
????????????return?new?X509Certificate[0];
????????}
????};
}

//实现信任所有域名的HostnameVerifier接口
private?static?class?TrustAllHostnameVerifier?implements?HostnameVerifier?{
????@Override
????public?boolean?verify(String?hostname,?SSLSession?session)?{
????????//域名校验,默认都通过
????????return?true;
????}
}

上面自定义X509TrustManager中的checkClientTreusted和checkServerTrusted都是空实现,也就是不检查客户端和服务端的SSL证书信息。另外在自定义HostnameVerifier中的verify方法返回true,默认信任所有域名,否则在请求时会报如下错误:

Hostname?XXX?not?verified:

2 根据自定义X509TrustManager创建OkHttpClient

将之前创建的空实现X509TrustManager传入createSSLClient方法,如下

private?static?OkHttpClient?createSSLClient(X509TrustManager?x509TrustManager){
????OkHttpClient.Builder?builder?=?new?OkHttpClient.Builder()
????????????.connectTimeout(60,?TimeUnit.SECONDS)
????????????.sslSocketFactory(createSSLSocketFactory(x509TrustManager),x509TrustManager)
????????????.hostnameVerifier(new?TrustAllHostnameVerifier());
????return?builder.build();
}

private?static?SSLSocketFactory?createSSLSocketFactory(TrustManager?trustManager)?{
????SSLSocketFactory?ssfFactory?=?null;
????try?{
????????SSLContext?sc?=?SSLContext.getInstance("TLS");
????????sc.init(null,?new?TrustManager[]{trustManager},?new?SecureRandom());
????????ssfFactory?=?sc.getSocketFactory();
????}?catch?(Exception?e)?{
????????e.printStackTrace();
????}
????return?ssfFactory;
}

通过上述方法,即可创建出不检查所有SSL证书的OkHttpClient对象。再次执行getBaidu和getTomcat方法,执行结果如下:

getBaidu?response:?
????<!DOCTYPE?html>
????<!--STATUS?OK--><html>?<head><meta?http-equiv=content-type?content=text/html;charset=utf-8><meta?http-equiv=X-UA-Compatible?content=IE=Edge><meta?content=always?name=referrer><link?rel=stylesheet?type=text/css?href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head>?<body?link=#0000cc>?<div?id=wrapper>?<div?id=head>?<div?class=head_wrapper>?<div?class=s_form>?<div?class=s_form_wrapper>?<div?id=lg>?<img?hidefocus=true?src=//www.baidu.com/img/bd_logo1.png?width=270?height=129>?</div>?<form?id=form?name=f?action=//www.baidu.com/s?class=fm>?<input?type=hidden?name=bdorz_come?value=1>?<input?type=hidden?name=ie?value=utf-8>?<input?type=hidden?name=f?value=8>?<input?type=hidden?name=rsv_bp?value=1>?<input?type=hidden?name=rsv_idx?value=1>?<input?type=hidden?name=tn?value=baidu><span?class="bg?s_ipt_wr"><input?id=kw?name=wd?class=s_ipt?value?maxlength=255?autocomplete=off?autofocus=autofocus></span><span?class="bg?s_btn_wr"><input?type=submit?id=su?value=百度一下?class="bg?s_btn"?autofocus></span>?</form>?</div>?</div>?<div?id=u1>?<a?href=http://news.baidu.com?name=tj_trnews?class=mnav>新闻</a>?<a?href=https://www.hao123.com?name=tj_trhao123?class=mnav>hao123</a>?<a?href=http://map.baidu.com?name=tj_trmap?class=mnav>地图</a>?<a?href=http://v.baidu.com?name=tj_trvideo?class=mnav>视频</a>?<a?href=http://tieba.baidu.com?name=tj_trtieba?class=mnav>贴吧</a>?<noscript>?<a?href=http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1?name=tj_login?class=lb>登录</a>?</noscript>?<script>document.write('<a?href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+?encodeURIComponent(window.location.href+?(window.location.search?===?""???"?"?:?"&")+?"bdorz_come=1")+?'"?name="tj_login"?class="lb">登录</a>');
????????????????????</script>?<a?href=//www.baidu.com/more/?name=tj_briicon?class=bri?style="display:?block;">更多产品</a>?</div>?</div>?</div>?<div?id=ftCon>?<div?id=ftConw>?<p?id=lh>?<a?href=http://home.baidu.com>关于百度</a>?<a?href=http://ir.baidu.com>About?Baidu</a>?</p>?<p?id=cp>&copy;2017&nbsp;Baidu&nbsp;<a?href=http://www.baidu.com/duty/>使用百度前必读</a>&nbsp;?<a?href=http://jianyi.baidu.com/?class=cp-feedback>意见反馈</a>&nbsp;京ICP证030173号&nbsp;?<img?src=//www.baidu.com/img/gs.gif>?</p>?</div>?</div>?</div>?</body>?</html>

getTomcat?response:?

????<!DOCTYPE?html>
????<html?lang="en">
????????<head>
????????????<meta?charset="UTF-8"?/>
????????????<title>Apache?Tomcat/8.5.72</title>
????????????<link?href="favicon.ico"?rel="icon"?type="image/x-icon"?/>
????????????<link?href="tomcat.css"?rel="stylesheet"?type="text/css"?/>
????????</head>

????????<body>
????????????<div?id="wrapper">
????????????????<div?id="navigation"?class="curved?container">
????????????????????<span?id="nav-home"><a?href="https://tomcat.apache.org/">Home</a></span>
????????????????????<span?id="nav-hosts"><a?href="/docs/">Documentation</a></span>
????????????????????<span?id="nav-config"><a?href="/docs/config/">Configuration</a></span>
????????????????????<span?id="nav-examples"><a?href="/examples/">Examples</a></span>
????????????????????<span?id="nav-wiki"><a?href="https://wiki.apache.org/tomcat/FrontPage">Wiki</a></span>
????????????????????<span?id="nav-lists"><a?href="https://tomcat.apache.org/lists.html">Mailing?Lists</a></span>
????????????????????<span?id="nav-help"><a?href="https://tomcat.apache.org/findhelp.html">Find?Help</a></span>
????????????????????<br?class="separator"?/>
????????????????</div>
????。。。
????</html>

可以看出,百度和Tomcat服务器的数据都能成功获取。但是这种方式存在极大的安全漏洞。因为并没有做任何SSL证书的校验,很容易被MITM(Man In The Middle)攻击。

比较好的优化方式当然是在客户端使用自签名SSL证书,验证服务器的身份合法之后,再进行后续的数据传输操作。通过以下步骤将客户端证书my_client.cer导入到项目中:

1 将my_client.cer保存在assets文件夹中

创建assets目录,并将my_client.cer保存到此目录下,如下:

2cf56b2607864b6de3ae7e976c3d250a.png

保存好后,通过如下方式将证书转换为InputStream格式:

private?InputStream?getInputStreamFromAsset(){
????InputStream?inputStream?=?null;
????try?{
????????inputStream?=?getAssets().open("my_clent.cer");
????}?catch?(IOException?e)?{
????????e.printStackTrace();
????}
????return?inputStream;
}

2 创建只信任自签名证书的X509TrustManager

将转换后的InputStream传入以下方法,创建自定义X509TrustManager

/**
?????*?创建只信任指定证书的TrustManager
?????*?@param?inputStream:证书输入流
?????*?@return
?????*/
????@Nullable
????private?static?X509TrustManager?createTrustCustomTrustManager(InputStream?inputStream)?{
????????try?{
????????????CertificateFactory?certificateFactory?=?CertificateFactory.getInstance("X.509");
????????????KeyStore?keyStore?=?KeyStore.getInstance(KeyStore.getDefaultType());
????????????keyStore.load(null);

????????????Certificate?certificate?=?certificateFactory.generateCertificate(inputStream);
????????????//将证书放入keystore中
????????????String?certificateAlias?=?"ca";
????????????keyStore.setCertificateEntry(certificateAlias,?certificate);
????????????if?(inputStream?!=?null)?{
????????????????inputStream.close();
????????????}

????????????TrustManagerFactory?trustManagerFactory?=?TrustManagerFactory.
????????????????????getInstance(TrustManagerFactory.getDefaultAlgorithm());
????????????trustManagerFactory.init(keyStore);
????????????TrustManager[]?trustManagers?=?trustManagerFactory.getTrustManagers();

????????????if?(trustManagers.length?!=?1?||?!(trustManagers[0]?instanceof?X509TrustManager))?{
????????????????throw?new?IllegalStateException("Unexpected?default?trust?managers:"
????????????????????????+?Arrays.toString(trustManagers));
????????????}
????????????return?(X509TrustManager)?trustManagers[0];
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????}
????????return?null;
????}

以上方法将自签名证书保存到Java对象KeyStore中,并最终创建只信任自签名证书的X509TrustManager对象。重新将此对象传给上文中的createSSLClient方法后,就是一个加载自签名SSL证书的OkHttpClient对象了。

再次执行getBaidu和getTomcat方法,执行结果如下:

getBaidu?onFailure:?java.security.cert.CertPathValidatorException:?Trust?anchor?for?certification?path?not?found.


getTomcat?response:?

????<!DOCTYPE?html>
????<html?lang="en">
????????<head>
????????????<meta?charset="UTF-8"?/>
????????????<title>Apache?Tomcat/8.5.72</title>
????????????<link?href="favicon.ico"?rel="icon"?type="image/x-icon"?/>
????????????<link?href="tomcat.css"?rel="stylesheet"?type="text/css"?/>
????????</head>

????????<body>
????????...
????????</body>
????</html>

以上结果显示获取baidu数据失败,而获取Tomcat数据成功。

log 显示结果正好跟最初的默认结果相反,这是因为当前所有的https请求都使用自签名证书去校验服务器身份。因为Tomcat配置了本地证书所以能够成功验明正身;但是baidu并没有配置我们的自签名证书,也就无法正确验明身份了。

c56067493b8b3a6e61c411d80d0ba3b7.gif

支持自签名证书和系统证书

为了能让getBaidu正常获取数据,并且getTomcat也在安全的环境下获取数据,我们需要在这个X509TrustManager中再添加对系统自带SSL证书的信任。具体如下:

/**
?*?创建既信任自签名证书又信任系统自带证书的TrustManager
?*/
private?static?X509TrustManager?createTrustCustomAndDefaultTrustManager(InputStream?inputStream)?{
????try?{
????????//?获取信任系统自带证书的TrustManager
????????final?X509TrustManager?systemTrustManager?=?getSystemTrustManager();
????????//?获取信任自签名证书的TrustManager
????????final?X509TrustManager?selfTrustManager?=?createTrustCustomTrustManager(inputStream);

????????return?new?X509TrustManager()?{
????????????@Override
????????????public?void?checkClientTrusted(X509Certificate[]?chain,?String?authType)?throws?CertificateException?{
????????????????systemTrustManager.checkClientTrusted(chain,?authType);
????????????}
????????????@Override
????????????public?void?checkServerTrusted(X509Certificate[]?chain,?String?authType)?throws?CertificateException?{
????????????????try?{
????????????????????//?默认使用信任自签名证书的TrustManager验证服务端身份
????????????????????selfTrustManager.checkServerTrusted(chain,?authType);
????????????????}?catch?(CertificateException?e)?{
????????????????????//?此处使用系统自带SSL证书验证服务端身份
????????????????????systemTrustManager.checkServerTrusted(chain,?authType);
????????????????}
????????????}
????????????@Override
????????????public?X509Certificate[]?getAcceptedIssuers()?{
????????????????return?systemTrustManager.getAcceptedIssuers();
????????????}
????????};
????}?catch?(Exception?e)?{
????????e.printStackTrace();
????}
????return?null;
}

/**
?*?创建信任系统自带证书的TrustManager
?*/
private?static?X509TrustManager?getSystemTrustManager()?throws?NoSuchAlgorithmException,?KeyStoreException?{
????TrustManagerFactory?tmf?=?TrustManagerFactory
????????????????.getInstance(TrustManagerFactory.getDefaultAlgorithm());

????tmf.init((KeyStore)?null);
????for?(TrustManager?tm?:?tmf.getTrustManagers())?{
????????if?(tm?instanceof?X509TrustManager)?{
????????????return?(X509TrustManager)?tm;
????????}
????}
????return?null;
}

可以看出在自定义X509TrustManager的checkServerTrusted方法中,先使用信任自签名证书的TrustManager验证服务端,如果没有验证成功,则继续使用系统默认TrustManager来继续验证。

通过以上设置之后,getBaidu?和?getTomcat这2个方法都能正确获取数据了。
对源码有需求,或者想一起探讨共同进步的,欢迎关注公众号发私信或者加微信。

f152f926cd83bed5baab5862cbc48fb9.gif

如果你喜欢本文

长按二维码关注

3ad0e9eaddfcde5475761c0a26ccb7c1.gif

f0e27d7fc70bf45548e9f79ea63f2a11.png

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-11-10 12:45:58  更:2021-11-10 12:48:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年7日历 -2024/7/1 21:32:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码