网站建设 客户拜访,腾讯wordpress 建站,免费咨询图片大全,网站开发总跳转至404页面1. 服务端数字证书验证的问题
在鸿蒙客户端对服务端发起HTTPS请求时#xff0c;如果使用HttpRequest的request发起请求#xff0c;那么就存在服务端数字证书的验证问题#xff0c;你只有两个选择#xff0c;一个是使用系统的CA#xff0c;一个是使用自己选定的CA#xf…1. 服务端数字证书验证的问题
在鸿蒙客户端对服务端发起HTTPS请求时如果使用HttpRequest的request发起请求那么就存在服务端数字证书的验证问题你只有两个选择一个是使用系统的CA一个是使用自己选定的CA在上文鸿蒙网络编程系列26-HTTPS证书自选CA校验示例中对此进行了介绍。但是还有一些更常见的问题难以解决 可不可以跳过对服务端数字证书的验证 可不可以自定义验证规则比如只验证数字证书的公玥忽略有效期就是说失效了也可以继续用
如果你还是使用HttpRequest的话答案是否定的。但是鸿蒙开发者很贴心的推出了远场通信服务可以使用rcp模块的方法发起请求并且在请求时指定服务端证书的验证方式关键点就在SecurityConfiguration接口上该接口的remoteValidation属性支持远程服务器证书的四种验证模式 system使用系统CA默认值 skip跳过验证 CertificateAuthority选定CA ValidationCallback自定义证书校验
Talk is cheap, show you the code
2. 实现HTTPS服务端证书四种校验方式示例
本示例运行后的界面如下所示 选择证书验证模式在请求地址输入要访问的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//服务端证书验证模式默认系统CAState 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服务端使用的是自签名证书然后单击“请求”按钮这时候会出现关于数字证书的错误信息如图所示 步骤6选择“指定CA”类型然后单击出现的“选择”按钮可以在本机选择CA证书文件然后单击“请求”按钮 可以看到得到了正确的请求结果。
步骤7选择“跳过验证”类型然后然后单击“请求”按钮 也得到了正确的请求结果。
步骤8选择“自定义验证”类型然后然后单击“请求”按钮 也得到了正确的请求结果。
3. 关键功能分析
关键点主要有两块第一块是设置验证模式 //服务器端证书验证模式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;}
这里为简单起见自定义规则是所有的验证都通过读者可以根据自己的需要来修改比如不验证证书的有效期。
本文作者原创除非明确授权禁止转载
本文源码地址
https://gitee.com/zl3624/harmonyos_network_samples/tree/master/code/rcp/RCPCertVerify
本系列源码地址
https://gitee.com/zl3624/harmonyos_network_samples