鸿蒙双向认证

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

相关文章

SpringSecurity JWT基于令牌的无状态认证实现

《SpringSecurityJWT基于令牌的无状态认证实现》SpringSecurity中实现基于JWT的无状态认证是一种常见的做法,本文就来介绍一下SpringSecurityJWT基于令牌的无... 目录引言一、JWT基本原理与结构二、Spring Security JWT依赖配置三、JWT令牌生成与

鸿蒙中Axios数据请求的封装和配置方法

《鸿蒙中Axios数据请求的封装和配置方法》:本文主要介绍鸿蒙中Axios数据请求的封装和配置方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1.配置权限 应用级权限和系统级权限2.配置网络请求的代码3.下载在Entry中 下载AxIOS4.封装Htt

鸿蒙中@State的原理使用详解(HarmonyOS 5)

《鸿蒙中@State的原理使用详解(HarmonyOS5)》@State是HarmonyOSArkTS框架中用于管理组件状态的核心装饰器,其核心作用是实现数据驱动UI的响应式编程模式,本文给大家介绍... 目录一、@State在鸿蒙中是做什么的?二、@Spythontate的基本原理1. 依赖关系的收集2.

SpringSecurity6.0 如何通过JWTtoken进行认证授权

《SpringSecurity6.0如何通过JWTtoken进行认证授权》:本文主要介绍SpringSecurity6.0通过JWTtoken进行认证授权的过程,本文给大家介绍的非常详细,感兴趣... 目录项目依赖认证UserDetailService生成JWT token权限控制小结之前写过一个文章,从S

springboot security使用jwt认证方式

《springbootsecurity使用jwt认证方式》:本文主要介绍springbootsecurity使用jwt认证方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录前言代码示例依赖定义mapper定义用户信息的实体beansecurity相关的类提供登录接口测试提供一

SpringSecurity 认证、注销、权限控制功能(注销、记住密码、自定义登入页)

《SpringSecurity认证、注销、权限控制功能(注销、记住密码、自定义登入页)》SpringSecurity是一个强大的Java框架,用于保护应用程序的安全性,它提供了一套全面的安全解决方案... 目录简介认识Spring Security“认证”(Authentication)“授权” (Auth

一文详解kafka开启kerberos认证的完整步骤

《一文详解kafka开启kerberos认证的完整步骤》这篇文章主要为大家详细介绍了kafka开启kerberos认证的完整步骤,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、kerberos安装部署二、准备机器三、Kerberos Server 安装1、配置krb5.con

java如何通过Kerberos认证方式连接hive

《java如何通过Kerberos认证方式连接hive》该文主要介绍了如何在数据源管理功能中适配不同数据源(如MySQL、PostgreSQL和Hive),特别是如何在SpringBoot3框架下通过... 目录Java实现Kerberos认证主要方法依赖示例续期连接hive遇到的问题分析解决方式扩展思考总

你的华为手机升级了吗? 鸿蒙NEXT多连推5.0.123版本变化颇多

《你的华为手机升级了吗?鸿蒙NEXT多连推5.0.123版本变化颇多》现在的手机系统更新可不仅仅是修修补补那么简单了,华为手机的鸿蒙系统最近可是动作频频,给用户们带来了不少惊喜... 为了让用户的使用体验变得很好,华为手机不仅发布了一系列给力的新机,还在操作系统方面进行了疯狂的发力。尤其是近期,不仅鸿蒙O

鸿蒙开发搭建flutter适配的开发环境

《鸿蒙开发搭建flutter适配的开发环境》文章详细介绍了在Windows系统上如何创建和运行鸿蒙Flutter项目,包括使用flutterdoctor检测环境、创建项目、编译HAP包以及在真机上运... 目录环境搭建创建运行项目打包项目总结环境搭建1.安装 DevEco Studio NEXT IDE