最新要闻
- 当前速讯:手机端ChatGPT搜索来了!微软2周火速上线 @Bing即用
- 多辆房车霸占高速服务区露营:有车主搭帐篷还晒咸菜
- 魔兽等游戏停服一个月 暴雪真不着急:两家中国公司抢破头
- 环球聚焦:《龙之家族》第二季明年首播
- 晨光文具批发总部电话_石家庄晨光办公用品有限公司
- 环球要闻:新款特斯拉Model 3实车谍照曝光:疑似加长、内饰大改
- 可口可乐风味饮品!柠檬道日式气泡酒大促:12罐不到30元
- 前沿资讯!《嗜血印》将推出女祭司1/4比例雕像 性感热辣吸睛
- 焦点快播:送礼新思路!淘宝公布2023年度丑东西:网红青蛙服入选“年度五丑”
- 名山大川是什么意思?名山大川有哪些?
- 喜欢被剧透的人是什么心理?喜欢被剧透的人是什么倾向?
- 每日快报!58岁清华毕业找不到超5000元工作 网友:我不是清华的咋办
- 天天热门:爷青结!《DNF》端游正式更名《地下城与勇士:创新世纪》:图标、文字调整
- 全球即时:《原子之心》优化非常好 但Xbox Series S仍存掉帧问题
- 精致又简约!雷孜LaCie新棱镜移动硬盘评测:速度全程稳如初
- 小米13 Ultra手机壳曝光:中分四摄、凸起严重
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
每日快讯!手把手教你为基于Netty的IM生成自签名SSL/TLS证书
1、引言
对于IM聊天应用来说,为了提升安全性,对聊天消息加密是常规操作。
众所周之,Netty是高性能的Java NIO网络通信框架,因而用Netty来写IM是再正常不过了。网上关于为Netty生成、以及使用SSL/TLS证书的文章有很多,但由于各种原因,生成的证书要么是Netty中无法读取和使用,要么是代码不全或不具体导致根本配不通SSL/TLS加密。
正好这段时间专门为MobileIMSDK生成了一套测试证书,顺手把这个过程记录了下来,分享给大家。
(相关资料图)
本文要分享的是如何使用OpenSSL生成在基于Netty的IM中真正可用的SSL/TLS证书,内容包括:证书的创建、创建过程中的注意点,以及在Server端、Android端、iOS端、Java桌面端、H5端使用证书的代码范例。
注:对于那些付费购买了第3方权威CA机构签发的证书,他们都有相应的使用文档,这就没什么好说的。本文里的证书指的是不需要花钱的自签名证书。
学习交流:
- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》
- 开源IM框架源码:https://github.com/JackJiang2011/MobileIMSDK(备用地址点此)
(本文已同步发布于:http://www.52im.net/thread-4142-1-1.html)
2、知识准备
► 如果你对IM系统毫无概念,建议先阅读《零基础IM开发入门(一):什么是IM系统?》系列文章,通俗易懂,适合小白。
► 如果你想系统学习IM开发相关的理论知识,比如网格编程、IM架构设计等,建议先阅读《新手入门一篇就够:从零开发移动端IM》。
►如果你不了解Netty是什么,建议阅读以下几篇Netty的基础入门好文章:
- 1)新手入门:目前为止最透彻的的Netty高性能原理和框架架构解析
- 2)写给初学者:Java高性能NIO框架Netty的学习方法和进阶策略
- 3)史上最通俗Netty框架入门长文:基本介绍、环境搭建、动手实战
► 如果你已掌握IM理论知识,同时也对Netty基本掌握,正准备动手实战,则可以阅读《基于Netty,从零开发IM》和《跟着源码学IM》这个系列文章,有各种入门级实战代码,图文并茂,适合学习。
► 如果你对IM、Netty已基本上手,但对IM安全方面的技术概念有点理不清,建议必读《基于Netty的IM聊天加密技术学习:一文理清常见的加密概念、术语等》。
3、什么是Netty
Netty是一个Java NIO技术的开源异步事件驱动的网络编程框架,用于快速开发可维护的高性能协议服务器和客户端。往通俗了讲,可以将Netty理解为:一个将Java NIO进行了大量封装,并大大降低Java NIO使用难度和上手门槛的超牛逼框架。(引用自《史上最通俗Netty框架入门长文:基本介绍、环境搭建、动手实战》)
PS:限于篇幅,对于Netty方面的入门知识就不再赘述,如有必要,请仔细跟着本文第二节“2、知识准备”里有关Netty的文章进行阅读。
4、什么是OpenSSL
OpenSSL是一个开放源代码的软件库,应用程序可以使用这个包来进行安全通信,它包括代码、脚本、配置和过程的集合。其主要库是以 C 语言所写成,实现了基本的加密功能,实现了 SSL 与 TLS 协议。OpenSSL整个软件包大概可以分成三个主要功能部分:SSL协议库、应用程序、密码算法库。
PS:OpenSSL的介绍就点到为止,如有兴趣,可仔细阅读《基于Netty的IM聊天加密技术学习:一文理清常见的加密概念、术语等》。
5、下载和安装OpenSSL
1)方法一:可以从OpenSSL的Github仓库下载源码自行编译(源码下载地址),对于一般使用者来说,自已编译着实有点麻烦,不推荐这么玩。
2)方法一:也可以从这个网站下载第3方编译好的OpenSSL安装程序(安装程序下载地址),这样上手简单快捷。具体可以参考《openssl安装教程(windows7系统,超详细)》这篇文章。
3)方法一:也可以直接用下面附件里的安装程序(这是我一直用的版本,版本较老,有兴趣可直接下载使用):
Openssl-windows-0.9.8k(52im.net).rar(874.97 KB, 下载次数:1, 售价:1金币)
4)解决 “openssl.cnf找不到” 的问题:如果你安装好OpenSSL后,使用时报“openssl.cnf找不到”或“计算机缺少openssl.cnf”等之类错误提示,可以下载下面这个openssl.cnf文件。
openssl.cnf文件附件下载:
openssl_conf(52im.net).rar(4.63 KB, 下载次数:1, 售价:1金币)
openssl.cnf文件解压缩后:
openssl.cnf文件配置使用:
以下是openssl.cnf文件的配置使用命令:(以我的安装目录为例)
C:\Openssl-windows-0.9.8k-out32dll>set OPENSSL_CONF=c:/WINDOWS/system32/openssl.cnf
准备就绪,接下来我们就可以开始生成SSL/TLS证书了!
6、生成Netty可用的SSL/TLS证书
6.1概述
经过实践,生成Netty可用的SSL/TLS证书需要4步:
- 1)创建私钥证书;
- 2)将私钥格式转成pk8;
- 3)创建证书请求;
- 4)生成公钥证书。
接下来,跟着本节内容,一步步使用OpenSSL生成一个真正能在Netty中能使用的自签名证书。
6.2第一步:创建私钥证书
在CMD控制台下执行如下指令:(记得手动创建netty目录)
openssl genrsa -des3 -out netty/netty-key.pem 1024
提示:以上指令中,如无“-des3”参数,则Netty的代码中使用时将报“File does not contain valid private key”等错误(如下图所示)。
6.3第二步:将私钥格式转成pk8
在CMD控制台下执行如下指令:
openssl pkcs8 -innetty/netty-key2.pem -topk8 -out netty/netty-key2.pk8
提示1:如不转pk8格式,则Netty的代码中使用时会报以下错误:
提示2:如代码中不为key加入密码,则Netty的代码中使用时会报以下错误:
提示3:Netty的代码中使用时要加入上方生成Key证书时的密码即可:
6.4第三步:创建证书请求
在CMD控制台下执行如下指令:
openssl req -new -out netty/netty-req2.csr -key netty/netty-key2.pem
提示:经上指令中,Common Name指明的是证书绑定的域名,你可以用域名或ip,本次生成用了子域名。
6.5第四步:生成公钥证书
在CMD控制台下执行如下指令:
openssl x509 -req -inca/ca-req2.csr -out netty/netty-cert2.crt -signkey netty/netty-key2.pem -days 3650
提示:out参数生成的是.crt,而在前面的是.pem,这只是扩展名区别,内容都一样。
6.6最终成果
至此,我们已经为Netty创建好了证书,接下来的章节,就是分享如何读取和使用这些证书的。
7、实战代码
7.1概述
本节将为你演示如何在基于Netty的IM中使用上节中生成的证书。
为了让示例代码更具实战意义,本节的示例代码将引用的是开源IM框架MobileIMSDK的源码,如果有兴趣深入学习,可以从下面的开源仓库中下载到MobileIMSDK的完整源码。
- 1)GitHub.com 托管地址:https://github.com/JackJiang2011/MobileIMSDK
- 2)码云gitee托管地址:https://gitee.com/jackjiang/MobileIMSDK
7.2基于Netty的IM服务端如何开启SSL/TLS
首先将上节中生成的证书,放置到你的IM服务端磁盘目录下。以下截图和示例代码以MobileIMSDK的开源代码为例。
我们可以将证书放到这个位置:
使用证书的示例代码片段:(完整代码详见ServerLauncherImpl.java)
/**
* 创建SslContext对象,用于开启SSL/TLS加密传输。
*
* @return 如果成功创建则返回SslContext对象,否则返回null
*/
privatestaticSslContext createSslContext() {
try{
// 证书文件
InputStream certChainFile = ServerLauncherImpl.class.getResourceAsStream("certs/netty-cert2.crt");
// 私钥文件(注意:Netty只支持.pk8格式)
InputStream keyFile = ServerLauncherImpl.class.getResourceAsStream("certs/netty-key2.pk8");
// 私钥密码
String keyPassword = "123456";
// 生成SslContext对象(为了方便理解,此处使用的是单向认证)
SslContext sslCtx = SslContextBuilder.forServer(certChainFile, keyFile, keyPassword).clientAuth(ClientAuth.NONE).build();
returnsslCtx;
} catch(Exception e) {
logger.warn("createSslContext()时出错了,原因:"+e.getMessage(), e);
}
returnnull;
}
PS:如果你想自已动手完整运行一下,可以阅读《MobileIMSDK的Demo使用帮助:Server端》。
接下来的内容,我们将实现客户端连接到使用SSL/TLS证书的Netty IM服务端。
7.3Android端如何开启SSL/TLS
因为服务端已经开启了SSL/TLS加密,我们在开发IM的客户端时,该如何启用SSL/TLS呢(否则你未开启SSL/TLS的客户端肯定是连不上你的服务端的)?
这里为了方便示例,我们同样以MobileIMSDK的Android端开源代码为例。
Android端开启SSL/TLS加密的示例代码片段:(完整代码详见IMClientManager.java)
/**
* 创建SslContext对象,用于开启SSL/TLS加密传输。
*
* @return 如果成功创建则返回SslContext对象,否则返回null
*/
publicSslContext createSslContext() {
SslContext sslContext = null;
try{
sslContext = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
Log.d(TAG, "【IMCORE-TCP】已开启SSL/TLS加密(单向认证),且sslContext创建成功。");
} catch(Exception e) {
Log.w(TAG, "【IMCORE-TCP】创建sslContext时出错,原因是:"+ e.getMessage(), e);
}
returnsslContext;
}
PS:如果你想自已动手完整运行一下,可以阅读《MobileIMSDK的Demo使用帮助:Android版》。
7.4iOS端如何开启SSL/TLS
同样的,iOS端该如何开启SSL/TLS呢?
这里我们依然以MobileIMSDK的iOS端开源代码为例(MobileIMSDK的iOS使用的是CocoaAsyncSocket网络库,如果你也是用的它,就可以直接参考了,因为开启了SSL/TLS的CocoaAsyncSocket代码跟未开启加密的代码用法差异较多,且这方面可以参考的资料较少)。
iOS端开启SSL/TLS加密的示例代码片段:(完整代码详见LocalSocketProvider.m)
/**
* 当socket已经完整连接并准备好读和写数据时,将调用此方法。
*/
- (void)socket:(MBGCDAsyncSocket *)socket didConnectToHost:(NSString*)host port:(uint16_t)port
{
if([ClientCoreSDK isENABLED_DEBUG])
NSLog(@"【IMCORE-TCP-SOCKET】成收到的了TCP的connect反馈, isConnected? %d、已开启ssl加密? %d", [socket isConnected], [ClientCoreSDK isSSL]);
// 如果未开启SSL加密传输,则正常进入连接完成后的代码逻辑
if(![ClientCoreSDK isSSL]) {
[selfwhenDidConnect:socket];
}
// 如果已开启SSL加密传输,则需要在回调中调用startTLS方法,以便实现跟服务端的SSL握手过程,
// 如果ssl握手成功,则会通过 socketDidSecure: 回调通知开发者
else{
// 配置 SSL/TLS 设置信息
NSMutableDictionary*settings = [NSMutableDictionarydictionaryWithCapacity:3];
// 允许自签名证书手动验证
[settings setObject:@YESforKey:GCDAsyncSocketManuallyEvaluateTrust];
// 经测试,本项不设置并不影响SSL的启用
// [settings setObject:@"此处填服务器IP地址" forKey:GCDAsyncSocketSSLPeerName];
// 如果不是自签名证书,而是权威证书颁发机构注册申请的证书,这个settings字典可不传(将使用GCDAsyncSocket的默认配置)
[socket startTLS:settings];
}
}
/**
* 当SSL握手成功后(也就是上方调用startSSL:方法后),将调用此方法。
*/
- (void)socketDidSecure:(MBGCDAsyncSocket *)socket
{
[selfwhenDidConnect:socket];
}
/**
* Allows a socket delegate to hook into the TLS handshake and manually validate the peer it"s connecting to.
*/
- (void)socket:(MBGCDAsyncSocket *)sock didReceiveTrust:(SecTrustRef)trust completionHandler:(void(^)(BOOLshouldTrustPeer))completionHandler
{
NSLog(@"【IMCORE-TCP-SOCKET】didReceiveTrust...");
// 以下没有做更复杂的ssl证书验证逻辑,如您需要实现更强大的双向认证等逻辑,可以参考这里:
// [url=https://github.com/FuangCao/cavan/blob/338ca8c09d6c78c5b38b95c6ffe994241afcc96e/xcode/TestSSL/TestSSL/ViewController.m]https://github.com/FuangCao/cava ... SL/ViewController.m[/url]
if(completionHandler) {
completionHandler(YES);
}
}
说明:CocoaAsyncSocket中开启SSL/TLS并不像Android和Java中那么简单,它不只是几行代码的事,而是整个数据读取逻辑的变化。
PS:如果你想自已动手完整运行一下,可以阅读《MobileIMSDK的Demo使用帮助:iOS版》。
7.5Java桌面端如何开启SSL/TLS
Java桌面端开启SSL/TLS的代码跟Android端是一样。我们同样以MobileIMSDK的Java端开源代码为例。
Java桌面端开启SSL/TLS加密的示例代码片段:(完整代码详见IMClientManager.java)
/**
* 创建SslContext对象,用于开启SSL/TLS加密传输。
*
* @return 如果成功创建则返回SslContext对象,否则返回null
*/
publicSslContext createSslContext() {
SslContext sslContext = null;
try{
sslContext = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
Log.d(TAG, "【IMCORE-TCP】已开启SSL/TLS加密(单向认证),且sslContext创建成功。");
} catch(Exception e) {
Log.w(TAG, "【IMCORE-TCP】创建sslContext时出错,原因是:"+ e.getMessage(), e);
}
returnsslContext;
}
PS:如果你想自已动手完整运行一下,可以阅读《MobileIMSDK的Demo使用帮助:Java版》。
7.6H5端如何开启SSL/TLS
我这里说的H5端,指的是能支持标准HTML5端WebSocket协议的PC浏览器端、手机移动端内嵌的Web引擎等场景。
H5端能开启SSL/TLS有两个前提:
- 1)第3方CA机构签发的SSL/TLS证书(这条是关键,不然浏览器因安全原因会阻止WebSocket连接的建立);
- 2)基于Netty的IM服务端已开启SSL/TLS(见本章“7.2 基于Netty的IM服务端如何开启SSL/TLS”)。
满足以上两点后,H5端什么代码都不需改动,只需将请求url由“ws”改成“wss”:
8、参考资料
[1]MobileIMSDK开源工程源码
[2]史上最通俗Netty框架入门长文:基本介绍、环境搭建、动手实战
[3]基于Netty,从零开发IM
[4]基于Netty的IM聊天加密技术学习:一文理清常见的加密概念、术语等
[5]IM聊天系统安全手段之通信连接层加密技术
[6]通俗易懂:一篇掌握即时通讯的消息传输安全原理
[7]探讨组合加密算法在IM中的应用
[8]openssl安装教程(windows7系统,超详细)
[9]WebSocket从入门到精通,半小时就够!
(本文已同步发布于:http://www.52im.net/thread-4142-1-1.html)
-
每日快讯!手把手教你为基于Netty的IM生成自签名SSL/TLS证书
本文要分享的是如何使用OpenSSL生成在基于Netty的IM中真正可用的SSL TLS证书,内容包括:证书的创建、...
来源: -
世界看点:数据治理如何做?火山引擎DataLeap帮助这款产品3个月降低计算成本20%
更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群本文讲述字节跳...
来源: 每日快讯!手把手教你为基于Netty的IM生成自签名SSL/TLS证书
当前热门:《我想进大厂》之Spring夺命连环10问
《分布式技术原理与算法解析》学习笔记Day20
世界看点:数据治理如何做?火山引擎DataLeap帮助这款产品3个月降低计算成本20%
世界今头条!装饰器设计模式这样学,保你必懂!
当前速讯:手机端ChatGPT搜索来了!微软2周火速上线 @Bing即用
多辆房车霸占高速服务区露营:有车主搭帐篷还晒咸菜
魔兽等游戏停服一个月 暴雪真不着急:两家中国公司抢破头
P1219 [USACO1.5]八皇后 Checker Challenge
世界新资讯:Java单元测试浅析(JUnit+Mockito)
81python装饰器
环球聚焦:《龙之家族》第二季明年首播
环球播报:Nginx基础03:配置文件nginx.conf(Part2)
【独家焦点】Python工具箱系列(二十六)
有奖调研!第五期(2022-2023)传统行业云原生技术落地调研——金融篇
全球快资讯丨A/B 测试成为企业“新窗口”:增长盈利告别经验主义,数据科学才是未来
晨光文具批发总部电话_石家庄晨光办公用品有限公司
环球要闻:新款特斯拉Model 3实车谍照曝光:疑似加长、内饰大改
可口可乐风味饮品!柠檬道日式气泡酒大促:12罐不到30元
前沿资讯!《嗜血印》将推出女祭司1/4比例雕像 性感热辣吸睛
焦点快播:送礼新思路!淘宝公布2023年度丑东西:网红青蛙服入选“年度五丑”
天天快报!C# Socket 通信时,怎样判断 Socket 双方是否断开连接
易基因|ChIP-seq等组学研究鉴定出结直肠癌的致癌超级增强子:Nature子刊
报道:顶象APP加固的“蜜罐”技术有什么作用
为什么带NOLOCK的查询语句还会造成阻塞
全球今亮点!支付宝二面:使用 try-catch 捕获异常会影响性能吗?大部分人都会答错!
名山大川是什么意思?名山大川有哪些?
喜欢被剧透的人是什么心理?喜欢被剧透的人是什么倾向?
每日快报!58岁清华毕业找不到超5000元工作 网友:我不是清华的咋办
天天热门:爷青结!《DNF》端游正式更名《地下城与勇士:创新世纪》:图标、文字调整
全球即时:《原子之心》优化非常好 但Xbox Series S仍存掉帧问题
精致又简约!雷孜LaCie新棱镜移动硬盘评测:速度全程稳如初
小米13 Ultra手机壳曝光:中分四摄、凸起严重
戴拿奥特曼飞鸟信扮演者怎么了?戴拿奥特曼的结局是什么?
四要十不准是什么意思?四要十不准内容有哪些?
童话故事是什么文体?出自童话故事的成语有哪些?
八门神器怎么打不开?八门神器使用教程
格兰仕电烤箱功能及使用方法有哪些?格兰仕电烤箱售后电话是多少?
智能abc输入法属于什么码?智能abc怎么打空格?
联想p700怎么样?联想p700手机参数?
thinkpad平板电脑怎么样?thinkpad平板电脑推荐
天天头条:Linux视频上传及压缩
Java 在线代码运行编译工具推荐
湖北长江产投将入股?集度汽车:正常交流活动
会员收入创单季最高!龚宇:爱奇艺已解决债务问题
每日焦点!原味、藤椒味 肉香酥脆:亚明农家小酥肉15元/斤狂促
【环球报资讯】大批玩家称玩《原子之心》恶心想吐!官方称将更新FOV设置
手机的飞行模式还有这些妙用!看到不点开后悔一生
【环球报资讯】C# 获取电脑内存、CPU信息
今热点:塔吉克斯坦发生7.2级地震:新疆多地震感强烈
简讯:世界第二大啤酒制造商!比尔盖茨收购喜力啤酒股份:花了62亿
环球讯息:一周扭转广告业务无果:马斯克再裁数十名Twitter员工
御香山
环球热资讯!邓超主演!《中国乒乓》出品人回应票房不如预期:希望接下来能卖多少是多少
当前观察:洗衣机买波轮还是滚筒 答案你一定想不到
世界热头条丨销量下滑45岁以上买断工龄?上汽通用辟谣:无裁员计划
腾讯自研!开放世界生存手游《黎明觉醒:生机》开服:不限号不删档
环球即时看!iPhone 15真机照首曝:刘海屏时代终结 灵动岛成标配
读Java实战(第二版)笔记18_基于Lambda的领域特定语言
沪上阿姨外包装旗袍图被质疑不雅 开叉至大腿根部不正常?官方回应
008 - 检验 (1)
JVM基础学习笔记
当前快报:Nvidia宣布GeForceNow将获得RTX服务器
天天日报丨辣椒越皱 就越辣?科学家好好研究了一番
全球时讯:128位《王者荣耀》选手通过职业技能等级考试 获“电子竞技员”证书
世界滚动:风云气象卫星今年两连发:中国将成全世界唯一!
【当前热闻】有开机广告用户照样买 全球电视销量TOP5 中国产占3席
Intel 56核心发烧U跑分逼近AMD 64核心:峰值功耗1100W!
世界热头条丨易企盈控股集团 深圳有限公司_对于易企盈控股集团 深圳有限公司简单介绍
fusion app自定义事件源码介绍(下)
Spring IOC官方文档学习笔记(十二)之基于Java的容器配置
【世界热闻】Flink之间的组件通信
Model 3还要便宜 分析师看衰特斯拉:不降价达不到目标
爱奇艺:《狂飙》热度刷新历史纪录 会员规模有信心继续增长
焦点热讯:Shell常用命令与脚本实例
每日热门:【算法训练营day58】LeetCode739. 每日温度 LeetCode496. 下一个更大元素
(三)浅谈人工智能:烽烟四起
【世界播资讯】Spark系列 - (2) Spark核心概念
每日简讯:ChatGPT承认:对人文学科 有3个负面影响
环球速讯:美女UP主买理想ONE一年血亏10万 欲哭无泪:我也要去维权
【算法训练营day57】LeetCode647. 回文子串 LeetCode516. 最长回文子序列
当前最新:006 - 数据类型、来源和清洗
焦点热议:跨境电商平台公布海外数字化展会首批重点名单 涵盖新能源等多个外贸核心行业
热讯:女孩用吹风机吹头发:插座处突然着火
播报:RTX 4060售价6999元 七彩虹将星X15 AT游戏本图赏
130MB/s读写稳如磐石!希捷酷玩系列蜘蛛侠特别版游戏硬盘2TB评测:RGB超有范儿
第七章 程序是在何种环境下运行的
二八轮动策略:基础与改进
Python迭代器是啥?
【世界速看料】学习笔记——Git命令
世界时讯:Vue相关笔记
吃面比吃米更易发胖 西安交大团队证实:三大原因
当前聚焦:中国联通空中基站研制成功:无人机留空最长8小时 信号覆盖100平方公里
爱玛MVP战神新国标电动两轮车直降千元:1499元 能跑40km
【天天报资讯】V社“钓鱼”打击外挂:《Dota 2》一次性封禁4万作弊玩家
全球聚焦:百度2022年赚了207亿 李彦宏放大招:多项业务整合文心一言
世界报道:Vue3从基础到精通
【算法训练营day56】LeetCode583. 两个字符串的删除工作 LeetCode72. 编辑距离
全球看点:孙正雯微博_孙正雯
女子连刷11个差评被曝光 当事人要起诉商家:视频流传到全网 严重影响生活