鸿蒙双向认证

2024-09-06 12:52
文章标签 认证 双向 鸿蒙

本文主要是介绍鸿蒙双向认证,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

鸿蒙双向认证

开发环境 基于API12

参考文档

切换到鸿蒙也要用上双向认证。使用的其中的 rcp 功能,详细文档https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/remote-communication-rcp-V5

双向认证包含两个方向,分为客户端验证服务端的证书和服务端验证客户端的证书。

客户端验证服务端的证书

这个就需要把服务端的证书内置在客户端里边,并且在请求的时候获取到服务端的证书,然后自己进行对比证书是否同内置的一样。

服务器证书的校验等级有以下几种:

  1. DefaultTrustEvaluator,使用默认的验证方式,验证证书的有效性,证书信任链那套
  2. RevocationTrustEvaluator,验证证书是否被吊销
  3. PinnedCertificatesTrustEvaluator,验证证书是否同本地的一致,可以是自签证书
  4. PublicKeysTrustEvaluator,验证证书的公钥,可以是自签证书,不过这个有个好处就是不用关心证书的有效期了
  5. CompositeTrustEvaluator,混合模式
  6. DisabledTrustEvaluator,不验证证书

可以按需自己处理。本文以对比公钥为例。

首先获取本地证书及证书的公钥。

let context = getContext(this)
const getRawFileContent = (ctx: Context, file: string) : string => {let buffer = ctx.resourceManager.getRawFileContentSync(file).bufferreturn String.fromCharCode(...new Uint8Array(buffer))
}function stringToUint8Array(str: string): Uint8Array {let arr: Array<number> = [];for (let i = 0, j = str.length; i < j; i++) {arr.push(str.charCodeAt(i));}return new Uint8Array(arr);
}const uInt8ToString = (buffer: Uint8Array): string => {return String.fromCharCode(...new Uint8Array(buffer))
}let serverCert: cert.X509Cert | null = null
let serverCertStr: string | null = nullcert.createX509Cert({data: stringToUint8Array(getRawFileContent(context, 'server.cer')),encodingFormat: cert.EncodingFormat.FORMAT_DER
}).then(x509Cert => {serverCert = x509CertserverCertStr = uInt8ToString(serverCert?.getPublicKey().getEncoded().data)
}).catch((error: BusinessError) => {
})

增加自定义验证证书函数。对比公钥是否一致。

{security: {remoteValidation: (context: rcp.ValidationContext) => {let tar = uInt8ToString(context.x509Certs[0].getPublicKey().getEncoded().data)if (serverCertStr === tar) {return true}return false},},
}

这样客户端就验证了服务端证书是否符合要求。

服务端验证客户端的证书

由于接口请求的问题,需要把客户端证书写入到沙盒里边,然后把沙盒地址传进去,就有点麻烦。

首先写入客户端证书到沙盒。

本文需要使用到crt及key两个文件。接口crt文件需要文本形式,但是key又需要沙盒地址。

const getRawFileContent = (ctx: Context, file: string) : string => {let buffer = ctx.resourceManager.getRawFileContentSync(file).bufferreturn String.fromCharCode(...new Uint8Array(buffer))
}let context = getContext(this)
let filesDir = context.filesDirfunction saveFile(fn: string) {let file = fs.openSync(filesDir + '/' + fn, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)let clientContent = context.resourceManager.getRawFileContentSync(fn)fs.writeSync(file.fd, clientContent.buffer)fs.fsyncSync(file.fd)fs.closeSync(file)
}saveFile('client.key')

然后提供客户端证书给服务端进行校验。

{security: {certificate: {content: getRawFileContent(context, 'client.crt'),key: filesDir + '/client.key',type: 'PEM',keyPassword: 'xxx'},},
}

这样就能把证书提供给服务端进行校验了。

完整实例

import { BusinessError } from '@ohos.base';
import { rcp } from "@kit.RemoteCommunicationKit";
import fs from '@ohos.file.fs';
import { cert } from '@kit.DeviceCertificateKit';
import { cryptoFramework } from '@kit.CryptoArchitectureKit';const getRawFileContent = (ctx: Context, file: string) : string => {let buffer = ctx.resourceManager.getRawFileContentSync(file).bufferreturn String.fromCharCode(...new Uint8Array(buffer))
}let context = getContext(this)
let filesDir = context.filesDirfunction saveFile(fn: string) {let file = fs.openSync(filesDir + '/' + fn, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)let clientContent = context.resourceManager.getRawFileContentSync(fn)fs.writeSync(file.fd, clientContent.buffer)fs.fsyncSync(file.fd)fs.closeSync(file)
}saveFile('client.key')function stringToUint8Array(str: string): Uint8Array {let arr: Array<number> = [];for (let i = 0, j = str.length; i < j; i++) {arr.push(str.charCodeAt(i));}return new Uint8Array(arr);
}const uInt8ToString = (buffer: Uint8Array): string => {return String.fromCharCode(...new Uint8Array(buffer))
}let serverCert: cert.X509Cert | null = null
let serverCertStr: string | null = nullcert.createX509Cert({data: stringToUint8Array(getRawFileContent(context, 'server.cer')),encodingFormat: cert.EncodingFormat.FORMAT_DER
}).then(x509Cert => {serverCert = x509CertserverCertStr = uInt8ToString(serverCert?.getPublicKey().getEncoded().data)
}).catch((error: BusinessError) => {console.error('createX509Cert failed, errCode: ' + error.code + ', errMsg: ' + error.message);
})const defaultTimeout: number = 60*1000const createRequestConfiguration = (timeout: number): rcp.Configuration => {return {security: {remoteValidation: (context: rcp.ValidationContext) => {let tar = uInt8ToString(context.x509Certs[0].getPublicKey().getEncoded().data)if (serverCertStr === tar) {return true}return false},certificate: {content: getRawFileContent(context, 'client.crt'),key: filesDir + '/client.key',type: 'PEM',keyPassword: 'xxx'},},transfer: {autoRedirect: true,timeout: {connectMs: 5000,transferMs: timeout,}}}
}const sessionConfig: rcp.SessionConfiguration = {requestConfiguration: createRequestConfiguration(defaultTimeout)
}const session: rcp.Session = rcp.createSession(sessionConfig)export const rcpget = (url:string, timeout: number = defaultTimeout):Promise<object> => {return new Promise((resolve, reject) => {let request = new rcp.Request(url, 'GET', getHeaders())if (timeout != defaultTimeout) {request.configuration = createRequestConfiguration(timeout)}session.fetch(request).then((response:rcp.Response) => {if (response.statusCode == 200) {resolve(data)} else {reject()}}).catch((err: BusinessError) => {reject()})})
}export const rcppost = (url: string, params: Record<string, string | number>, timeout: number = defaultTimeout):Promise<object> => {let p: string[] = []for(let kv of Object.entries(params)) {p.push(`${kv[0]}=${kv[1]}`)}let pstr: string = p.join('&')return new Promise((resolve, reject) => {let request: rcp.Requestif (pstr == '') {request = new rcp.Request(url, 'POST', getHeaders())} else {request = new rcp.Request(url, 'POST', getHeaders(), pstr)}if (timeout != defaultTimeout) {request.configuration = createRequestConfiguration(timeout)}session.fetch(request).then((response:rcp.Response) => {if (response.statusCode == 200) {resolve(data)} else {reject()}}).catch((err: BusinessError) => {reject()})})
}

如此这般就能实现双向认证。感觉安全级别又上了一个等级。

这篇关于鸿蒙双向认证的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1142058

相关文章

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

csu1329(双向链表)

题意:给n个盒子,编号为1到n,四个操作:1、将x盒子移到y的左边;2、将x盒子移到y的右边;3、交换x和y盒子的位置;4、将所有的盒子反过来放。 思路分析:用双向链表解决。每个操作的时间复杂度为O(1),用数组来模拟链表,下面的代码是参考刘老师的标程写的。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#

【Kubernetes】K8s 的安全框架和用户认证

K8s 的安全框架和用户认证 1.Kubernetes 的安全框架1.1 认证:Authentication1.2 鉴权:Authorization1.3 准入控制:Admission Control 2.Kubernetes 的用户认证2.1 Kubernetes 的用户认证方式2.2 配置 Kubernetes 集群使用密码认证 Kubernetes 作为一个分布式的虚拟

鸿蒙开发中实现自定义弹窗 (CustomDialog)

效果图 #思路 创建带有 @CustomDialog 修饰的组件 ,并且在组件内部定义controller: CustomDialogController 实例化CustomDialogController,加载组件,open()-> 打开对话框 , close() -> 关闭对话框 #定义弹窗 (CustomDialog)是什么? CustomDialog是自定义弹窗,可用于广告、中

【Shiro】Shiro 的学习教程(二)之认证、授权源码分析

目录 1、背景2、相关类图3、解析3.1、加载、解析阶段3.2、认证阶段3.3、授权阶段 1、背景 继上节代码,通过 debug 进行 shiro 源码分析。 2、相关类图 debug 之前,先了解下一些类的结构图: ①:SecurityManager:安全管理器 DefaultSecurityManager: RememberMeManager:实现【记住我】功能

react笔记 8-19 事件对象、获取dom元素、双向绑定

1、事件对象event 通过事件的event对象获取它的dom元素 run=(event)=>{event.target.style="background:yellowgreen" //event的父级为他本身event.target.getAttribute("aid") //这样便获取到了它的自定义属性aid}render() {return (<div><h2>{

OpenStack离线Train版安装系列—3控制节点-Keystone认证服务组件

本系列文章包含从OpenStack离线源制作到完成OpenStack安装的全部过程。 在本系列教程中使用的OpenStack的安装版本为第20个版本Train(简称T版本),2020年5月13日,OpenStack社区发布了第21个版本Ussuri(简称U版本)。 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版

OpenStack Victoria版——3.控制节点-Keystone认证服务组件

3.控制节点-Keystone认证服务组件 更多步骤:OpenStack Victoria版安装部署系列教程 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版 离线安装部署系列教程(全) OpenStack Train版 离线安装部署系列教程(全) 欢迎留言沟通,共同进步。 文章目录 创建key

【鸿蒙HarmonyOS NEXT】页面之间相互传递参数

【鸿蒙HarmonyOS NEXT】页面之间相互传递参数 一、环境说明二、页面之间相互传参 一、环境说明 DevEco Studio 版本: API版本:以12为主 二、页面之间相互传参 说明: 页面间的导航可以通过页面路由router模块来实现。页面路由模块根据页面url找到目标页面,从而实现跳转。通过页面路由模块,可以使用不同的url访问不同的页面,包括跳转到U