鸿蒙Harmony编程开发:HTTPS服务端证书四种校验方式

如果你还是使用HttpRequest的话,答案是否定的。但是,鸿蒙开发者很贴心的推出了远场通信服务,可以使用rcp模块的方法发起请求,并且在请求时指定服务端证书的验证方式,关键点就在SecurityConfiguration接口上,该接口的remoteValidation属性支持远程服务器证书的四种验证模式:

  • 'system':使用系统CA,默认值
  • 'skip':跳过验证
  • CertificateAuthority:选定CA
  • ValidationCallback:自定义证书校验

Talk is cheap, show you the code!

实现HTTPS服务端证书四种校验方式示例

本示例运行后的界面如下所示:

cke_54800.jpg

选择证书验证模式,在请求地址输入要访问的https网址,然后单击“请求”按钮,就可以在下面的日志区域显示请求结果。

下面详细介绍创建该应用的步骤。

步骤1:创建Empty Ability项目。

步骤2:在module.json5配置文件加上对权限的声明:

"requestPermissions": [{"name": "ohos.permission.INTERNET"}]这里添加了获取互联网信息的权限。复制

步骤3:在Index.ets文件里添加如下的代码:

import util from '@ohos.util';
import picker from '@ohos.file.picker';
import fs from '@ohos.file.fs';
import { BusinessError } from '@kit.BasicServicesKit';
import { rcp } from '@kit.RemoteCommunicationKit';@Entry
@Component
struct Index {//连接、通讯历史记录@State msgHistory: string = ''//请求的HTTPS地址@State httpsUrl: string = "https://47.**.**.***:8081/hello"//服务端证书验证模式,默认系统CA@State certVerifyType: number = 0//是否显示选择CA的组件@State selectCaShow: Visibility = Visibility.None//选择的ca文件@State caFileUri: string = ''scroller: Scroller = new Scroller()build() {Row() {Column() {Text("远场通讯HTTPS证书校验示例").fontSize(14).fontWeight(FontWeight.Bold).width('100%').textAlign(TextAlign.Center).padding(10)Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {Text("选择服务器HTTPS证书的验证模式:").fontSize(14).width(90).flexGrow(1)}.width('100%').padding(10)Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {Column() {Text('系统CA').fontSize(14)Radio({ value: '0', group: 'rgVerify' }).checked(true).height(50).width(50).onChange((isChecked: boolean) => {if (isChecked) {this.certVerifyType = 0}})}Column() {Text('指定CA').fontSize(14)Radio({ value: '1', group: 'rgVerify' }).checked(false).height(50).width(50).onChange((isChecked: boolean) => {if (isChecked) {this.certVerifyType = 1}})}Column() {Text('跳过验证').fontSize(14)Radio({ value: '2', group: 'rgVerify' }).checked(false).height(50).width(50).onChange((isChecked: boolean) => {if (isChecked) {this.certVerifyType = 2}})}Column() {Text('自定义验证').fontSize(14)Radio({ value: '3', group: 'rgVerify' }).checked(false).height(50).width(50).onChange((isChecked: boolean) => {if (isChecked) {this.certVerifyType = 3}})}}.width('100%').padding(10)Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {Text("服务端证书CA").fontSize(14).width(90).flexGrow(1)Button("选择").onClick(() => {this.selectCA()}).width(70).fontSize(14)}.width('100%').padding(10).visibility(this.certVerifyType == 1 ? Visibility.Visible : Visibility.None)Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {Text("请求地址:").fontSize(14).width(80)TextInput({ text: this.httpsUrl }).onChange((value) => {this.httpsUrl = value}).width(110).fontSize(12).flexGrow(1)Button("请求").onClick(() => {this.doHttpRequest()}).width(60).fontSize(14)}.width('100%').padding(10)Scroll(this.scroller) {Text(this.msgHistory).textAlign(TextAlign.Start).padding(10).width('100%').backgroundColor(0xeeeeee)}.align(Alignment.Top).backgroundColor(0xeeeeee).height(300).flexGrow(1).scrollable(ScrollDirection.Vertical).scrollBar(BarState.On).scrollBarWidth(20)}.width('100%').justifyContent(FlexAlign.Start).height('100%')}.height('100%')}//自定义证书验证方式selfDefServerCertValidation: rcp.ValidationCallback = (context: rcp.ValidationContext) => {//此处编写证书有效性判断逻辑return true;}//生成rcp配置信息buildRcpCfg() {let caCert: rcp.CertificateAuthority = {content: this.getCAContent()}//服务器端证书验证模式let certVerify: 'system' | 'skip' | rcp.CertificateAuthority | rcp.ValidationCallback = "system"if (this.certVerifyType == 0) { //系统验证certVerify = 'system'} else if (this.certVerifyType == 1) { //选择CA证书验证certVerify =caCert} else if (this.certVerifyType == 2) { //跳过验证certVerify = 'skip'} else if (this.certVerifyType == 3) { //自定义证书验证certVerify = this.selfDefServerCertValidation}let secCfg: rcp.SecurityConfiguration = { remoteValidation: certVerify }let reqCfg: rcp.Configuration = { security: secCfg }let sessionCfg: rcp.SessionConfiguration = { requestConfiguration: reqCfg }return sessionCfg}//发起http请求doHttpRequest() {let rcpCfg = this.buildRcpCfg()let rcpSession: rcp.Session = rcp.createSession(rcpCfg)rcpSession.get(this.httpsUrl).then((response) => {if (response.body != undefined) {let result = buf2String(response.body)this.msgHistory += '请求响应信息: ' + result + "\r\n";}}).catch((err: BusinessError) => {this.msgHistory += `err: err code is ${err.code}, err message is ${JSON.stringify(err)}\r\n`;})}//选择CA证书文件selectCA() {let documentPicker = new picker.DocumentViewPicker();documentPicker.select().then((result) => {if (result.length > 0) {this.caFileUri = result[0]this.msgHistory += "select file: " + this.caFileUri + "\r\n";}}).catch((e: BusinessError) => {this.msgHistory += 'DocumentViewPicker.select failed ' + e.message + "\r\n";});}//加载CA文件内容getCAContent(): string {let caContent = ""try {let buf = new ArrayBuffer(1024 * 4);let file = fs.openSync(this.caFileUri, fs.OpenMode.READ_ONLY);let readLen = fs.readSync(file.fd, buf, { offset: 0 });caContent = buf2String(buf.slice(0, readLen))fs.closeSync(file);} catch (e) {this.msgHistory += 'readText failed ' + e.message + "\r\n";}return caContent}
}//ArrayBuffer转utf8字符串
function buf2String(buf: ArrayBuffer) {let msgArray = new Uint8Array(buf);let textDecoder = util.TextDecoder.create("utf-8");return textDecoder.decodeWithStream(msgArray)
}

步骤4:编译运行,可以使用模拟器或者真机。

步骤5:选择默认“系统CA”,输入请求网址(假设web服务端使用的是自签名证书),然后单击“请求”按钮,这时候会出现关于数字证书的错误信息,如图所示:

cke_63643.jpg

步骤6:选择“指定CA”类型,然后单击出现的“选择”按钮,可以在本机选择CA证书文件,然后单击“请求”按钮:

cke_129996.jpg

可以看到,得到了正确的请求结果。

步骤7:选择“跳过验证”类型,然后然后单击“请求”按钮:

cke_159268.jpg

也得到了正确的请求结果。

步骤8:选择“自定义验证”类型,然后然后单击“请求”按钮:

cke_253658.jpg

也得到了正确的请求结果。

关键功能分析

关键点主要有两块,第一块是设置验证模式:

    //服务器端证书验证模式let certVerify: 'system' | 'skip' | rcp.CertificateAuthority | rcp.ValidationCallback = "system"if (this.certVerifyType == 0) { //系统验证certVerify = 'system'} else if (this.certVerifyType == 1) { //选择CA证书验证certVerify =caCert} else if (this.certVerifyType == 2) { //跳过验证certVerify = 'skip'} else if (this.certVerifyType == 3) { //自定义证书验证certVerify = this.selfDefServerCertValidation}let secCfg: rcp.SecurityConfiguration = { remoteValidation: certVerify }let reqCfg: rcp.Configuration = { security: secCfg }let sessionCfg: rcp.SessionConfiguration = { requestConfiguration: reqCfg }return sessionCfg}

这个比较好理解,第二块是自定义证书验证的方法:

  //自定义证书验证方式selfDefServerCertValidation: rcp.ValidationCallback = (context: rcp.ValidationContext) => {//此处编写证书有效性判断逻辑return true;}

这里为简单起见,自定义规则是所有的验证都通过,读者可以根据自己的需要来修改,比如不验证证书的有效期。

最后

小编在之前的鸿蒙系统扫盲中,有很多朋友给我留言,不同的角度的问了一些问题,我明显感觉到一点,那就是许多人参与鸿蒙开发,但是又不知道从哪里下手,因为资料太多,太杂,教授的人也多,无从选择。有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。 

为了确保高效学习,建议规划清晰的学习路线,涵盖以下关键阶段:

希望这一份鸿蒙学习资料能够给大家带来帮助~


 鸿蒙(HarmonyOS NEXT)最新学习路线

该路线图包含基础技能、就业必备技能、多媒体技术、六大电商APP、进阶高级技能、实战就业级设备开发,不仅补充了华为官网未涉及的解决方案

路线图适合人群:

IT开发人员:想要拓展职业边界
零基础小白:鸿蒙爱好者,希望从0到1学习,增加一项技能。
技术提升/进阶跳槽:发展瓶颈期,提升职场竞争力,快速掌握鸿蒙技术

2.视频学习资料+学习PDF文档

(鸿蒙语法ArkTS、TypeScript、ArkUI教程……)

 纯血版鸿蒙全套学习资料(面试、文档、全套视频等)

                   

鸿蒙APP开发必备

​​

总结

参与鸿蒙开发,你要先认清适合你的方向,如果是想从事鸿蒙应用开发方向的话,可以参考本文的学习路径,简单来说就是:为了确保高效学习,建议规划清晰的学习路线

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/407923.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kafka·概述

概览 Producer 生产者发送消息给broker,并不是生成一条消息后立刻发送,而是积攒多条后,批量发送到broker。可以通过配置参数batch.size(单位字节)调整积攒多少后发送 Consumer Topic 消息的分类 当Producer发送指定…

OpenAI 重回巅峰:ChatGPT-4O 最新模型超越谷歌 Gemini 1.5,多项测试夺冠!

谷歌上周发布的Gemini 1.5 Pro模型,在LMSYS办的聊天机器人竞技场Chatbot Arena中获得第一名。但是,OpenAI迅速反应,推出了最新的chatgpt-4o-latest模型,重新夺回了冠军头衔。 chatgpt-4o-latest模型简介 OpenAI最近推出了名为gpt-…

Unity教程(十二)视差背景

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程(零)Unity和VS的使用相关内容 Unity教程(一)开始学习状态机 Unity教程(二)角色移动的实现 Unity教程(三)角色跳跃的实现 Unity教程&…

C语言-从键盘输入一个字符串,将其中的小写字母全部转换成大写字母,然后输出到一个磁盘文件test中保存,输人的字符串以“!”结束

题目要求&#xff1a; 从键盘输入一个字符串,将其中的小写字母全部转换成大写字母,然后输出到一个磁盘文件test中保存,输人的字符串以"!”结束 1.实现程序&#xff1a; #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int main() {FILE* fp fopen("…

鸿蒙内核源码分析(用户态锁篇) | 如何使用快锁Futex(上)

快锁上下篇 鸿蒙内核实现了Futex&#xff0c;系列篇将用两篇来介绍快锁&#xff0c;主要两个原因: 网上介绍Futex的文章很少&#xff0c;全面深入内核介绍的就更少&#xff0c;所以来一次详细整理和挖透。涉及用户态和内核态打配合&#xff0c;共同作用&#xff0c;既要说用户…

深入理解滑动窗口算法及其经典应用

文章目录 什么是滑动窗口&#xff1f;经典题型分析与讲解**1. 长度最小的子数组****2. 无重复字符的最长子串****3. 最长重复子数组****4. 将x减到0的最小操作数**5. 水果成篮 (LeetCode 904)6. 滑动窗口最大值 (LeetCode 239)7. 字符串中的所有字母异位词 (LeetCode 剑指 Offe…

区块链基础通识(1)——分布式系统的共识问题

分布式系统 我们最初了解区块链的时候&#xff0c;很多人会形容这个区块链是一个“分布式的不可篡改账本”&#xff0c;这是一个很形象的说法&#xff0c;但是我认为更为准确的形容是“所有节点共同维护的状态机”。为什么分布式和区块链不能划等号呢&#xff1f; 两种常见的…

数字身份革命:探索Web3对个人隐私的保护

在数字化时代&#xff0c;个人隐私和数据保护成为越来越重要的话题。随着Web3的兴起&#xff0c;这一领域正在经历一场深刻的变革。Web3不仅仅是技术的演进&#xff0c;更是对个人隐私保护的一次革命性革新。本文将探讨Web3如何通过去中心化技术重新定义数字身份&#xff0c;并…

npm install报错,解决记录:11个步骤诊断和解决问题

在处理npm install报错时&#xff0c;可以遵循以下步骤来诊断和解决问题&#xff1a; 查看错误信息&#xff1a; 错误信息通常会给出问题的线索&#xff0c;例如依赖包版本冲突、网络问题、权限问题等。 更新npm和Node.js&#xff1a; 首先尝试更新npm和Node.js到最新版本&…

电子电气架构--- 智能汽车电子架构的核心诉求

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 屏蔽力是信息过载时代一个人的特殊竞争力&#xff0c;任何消耗你的人和事&#xff0c;多看一眼都是你的不…

Windows平台SDKMAN工具使用

为方便jvm生态的软件版本管理&#xff0c;可以使用sdkman工具来安装和管理诸如java、gradle等软件的当前使用版本。尤其是大多数程序员都是在windows平台开发&#xff0c;团队开发通常都需要统一的jvm相关软件的版本。这里给大家演示下windows平台如何安装和使用sdkman来实现这…

安全架构设计

目录 1安全需求分析 2安全架构原则 3安全架构方法 系统架构完整实例_系统架构设计案例-CSDN博客 1安全概述 系统安全架构设计&#xff0c;主要包含&#xff1a;物理安全&#xff0c;网络安全&#xff0c;系统安全&#xff0c;数据安全&#xff0c;应用安全。 完整性(Integ…

内存管理篇-05物理页面的迁移类型migratetype

本节内容依旧是对上节课伙伴系统的补充&#xff0c;主要介绍了新版伙伴系统的页面迁移相关的内容 为什么要引入页面迁移类型&#xff1f;新版本伙伴系统针对老版本的伙伴系统的升级改进。主要优化memory compaction内存碎片整理的过程。 页面迁移实际上就是伙伴系统中free_area…

构建高效的串行任务执行器:SerialExecutor深度解析

本文主要介绍怎么去实现一个支持串行执行任务的SerialExecutor执行器 摘要 在复杂的异步编程中&#xff0c;有时我们需要确保任务以串行的方式执行&#xff0c;以维护任务间的依赖关系或顺序。SerialExecutor 是一个自定义的执行器&#xff0c;它封装了 Java 的 Executor 接口…

leetcode 3 无重复字符的最长子串

leetcode 3 无重复字符的最长子串 正文普通解法双指针 正文 普通解法 重点观察示例 3。本题重点是创建一个动态区间&#xff0c;然后判断位于这个动态区间之外的字符是否被包含在这个动态区间范围内。并且对于 s 长度小于 1 的情况要重点进行讨论。 class Solution:def lengt…

day38.动态规划+MySql数据库复习

844.比较含退格的字符串 给定 s 和 t 两个字符串&#xff0c;当它们分别被输入到空白的文本编辑器后&#xff0c;如果两者相等&#xff0c;返回 true 。# 代表退格字符。 注意&#xff1a;如果对空文本输入退格字符&#xff0c;文本继续为空 思路:定义两个栈&#xff0c;将字符…

后端完成api顺序

contoroller层 Service层 点击getById&#xff0c;如果没有getById函数就先声明一个 然后完成函数体 db层 数据访问对象.数据库方法 //作用是提供对数据库中特定表的操作方法

20. elasticsearch进阶_数据可视化与日志管理

20. 数据可视化 本章概述一. `elasticsearch`实现数据统计1.1 创建用户信息索引1.1.1 控制台创建`aggs_user`索引1.1.2 `aggs_user`索引结构初始化1.1.3 `aggs_user`索引的`EO`对象1.1.4 用户类型枚举1.1.5 数据初始化1.2 内置统计聚合1.2.1 `terms`与`date_histogram``terms``…

C语言基础(十五)

指针的使用&#xff1a; 测试代码1&#xff1a; #include <stdio.h> // 标准的 main 函数声明&#xff0c;包括可选的 envp 参数 int main(int argc, char *argv[], char *envp[]) { // argc 命令行参数的数量&#xff08;包括程序名&#xff09; // argv 指向字…

【html+css 绚丽Loading】000015 九转轮回珠

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽Loading&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495…