news 2026/4/16 14:23:28

Vue3证书信息查看工具实现方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue3证书信息查看工具实现方案

本文记录「证书信息查看」这个工具在本项目中的实现方案,主要围绕 Vue 端页面结构和功能 JS 逻辑展开,方便后续维护和扩展同类工具。

在线工具网址:https://see-tool.com/certificate-info-viewer
工具截图:

页面结构与状态设计

证书信息查看页面基于 Vue 3<script setup>编写,核心分为三块:

  • 输入区:通过inputType区分「粘贴证书文本」「上传证书文件」「输入域名查询」三种模式,对应不同的输入控件。
  • 结果展示区:依赖resultData渲染证书主体信息、签发者信息和证书详情三大表格,字段配置用subjectFieldsissuerFieldscertFields这些computed从配置/文案中统一读取。
  • 操作区:提供「查询」「清空」按钮,以及在有结果时的「下载证书 PEM」「下载公钥 PEM」按钮。

页面内部通过一组ref保存当前状态:inputTypecertContentdomainInputselectedFileselectedFileNameisDragOverisLoadingerrorMessageresultData等,这些状态与模板上的v-model、条件渲染和按钮禁用态形成一套比较清晰的单向数据流。

constinputType=ref<'paste'|'file'|'domain'>('paste')constcertContent=ref('')constdomainInput=ref('')constselectedFile=ref<File|null>(null)constselectedFileName=ref('')constisDragOver=ref(false)constisLoading=ref(false)consterrorMessage=ref('')constresultData=ref<any|null>(null)constsubjectFields=computed(()=>tm('certificateInfoViewer.result.subjectFields')||[])constissuerFields=computed(()=>tm('certificateInfoViewer.result.issuerFields')||[])constcertFields=computed(()=>tm('certificateInfoViewer.result.certFields')||[])

输入校验与错误提示

在触发查询前,所有输入都会先经过validateInput()

  • 当模式是「粘贴文本」时,要求certContent非空;
  • 当模式是「上传文件」时,要求已选择selectedFile
  • 当模式是「域名查询」时,要求domainInput非空。

错误信息使用统一的setError(code, fallback)函数设置,内部会通过resolveErrorMessage先按错误码查映射表,找不到时再退回到兜底文案,同时调用notify在页面右上角弹出提示,这样前端各处只需要抛出语义化的错误码即可。

constresolveErrorMessage=(code:string,fallback?:string)=>{constmapped=errorMap.value?.[code]if(mapped)returnmappedif(fallback)returnfallbackreturnt('certificateInfoViewer.messages.queryFailed')}constsetError=(code:string,fallback?:string)=>{errorMessage.value=resolveErrorMessage(code,fallback)notify(errorMessage.value,'error')}constvalidateInput=()=>{if(inputType.value==='paste'&&!certContent.value.trim()){setError('CONTENT_REQUIRED')returnfalse}if(inputType.value==='file'&&!selectedFile.value){setError('FILE_EMPTY')returnfalse}if(inputType.value==='domain'&&!domainInput.value.trim()){setError('DOMAIN_REQUIRED')returnfalse}returntrue}

文件上传与拖拽处理

针对证书文件上传,页面实现了一套独立的小模块:

  • 使用setSelectedFile(file)做统一入口,校验文件大小(maxFileSize)和扩展名(allowedExtensions,只允许.pem/.crt/.cer),并更新selectedFileselectedFileName
  • handleFileChange负责响应<input type="file">的变更事件,handleDragOver/handleDragLeave/handleDrop则实现拖拽高亮和文件接收逻辑。
  • 当输入方式切换为非文件模式时,通过监听inputTypewatch自动清空已选择的文件,避免状态残留。

这部分逻辑和 UI 解耦较好,未来如果要复用到其他上传类工具,只需要复用这几个函数即可。

constmaxFileSize=10*1024*1024constallowedExtensions=['.pem','.crt','.cer']constgetFileExtension=(filename:string)=>{constlastDot=filename.lastIndexOf('.')if(lastDot===-1)return''returnfilename.slice(lastDot).toLowerCase()}constsetSelectedFile=(file:File|null)=>{if(!file){selectedFile.value=nullselectedFileName.value=''return}if(file.size>maxFileSize){setError('FILE_TOO_LARGE')return}constext=getFileExtension(file.name)if(!allowedExtensions.includes(ext)){setError('FILE_TYPE_NOT_ALLOWED')return}selectedFile.value=file selectedFileName.value=file.name}consthandleDrop=(event:DragEvent)=>{isDragOver.value=falseconstfile=event.dataTransfer?.files?.[0]||nullsetSelectedFile(file)}

证书查询与上传请求

两种请求方式的区别在于请求体构造和上传方式:

  • 文本 / 域名模式queryCertificateInfo()先构造包含modecontentdomainpayload,然后以 JSON 形式fetch('/api/certificate-info')
  • 文件上传模式uploadCertificate()构造包含modefilenamepayload,再创建FormData,将文件二进制和相关字段一起塞入,以 multipart 方式fetch('/api/certificate-info-upload')

对应的后端 API 在接收到请求后,大致会做三件事:首先根据mode决定是从文本、上传文件还是目标域名中取出证书原始数据;然后对证书做解析与字段提取,生成主体信息、签发者信息、有效期、用途、SAN 等结构化结果,并计算 SHA 指纹等摘要;最后把格式化好的subjectInfoissuerInfocertInfo以及可下载的证书、公钥 PEM 文本一并封装成data返回给前端。
其中「域名查询」模式下,服务端会先把用户输入的 URL 解析成hostport,在 Node.js 环境中发起一次 TLS 连接,仅完成握手就从连接中拿到对端证书的原始二进制数据,随后走与文本/文件模式相同的解析与字段提取流程。

两种请求都会对返回的result.status做统一判断,不为ok则通过setError(result.message, result.message)报错,为ok时把result.data写入resultData,驱动页面结果区渲染。

constqueryCertificateInfo=async()=>{constpayload={mode:pendingType.value,content:certContent.value.trim(),domain:domainInput.value.trim()}try{constresponse=awaitfetch('/api/certificate-info',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)})constresult=awaitresponse.json()if(result.status!=='ok'){setError(result.message,result.message)return}resultData.value=result.data}catch(error:any){setError('REQUEST_FAILED',error?.message)}}constuploadCertificate=async()=>{if(!selectedFile.value){setError('FILE_EMPTY')return}constpayload={mode:'upload',filename:selectedFile.value.name}try{constformData=newFormData()formData.append('cert',selectedFile.value)Object.entries(payload).forEach(([key,value])=>{formData.append(key,String(value))})constresponse=awaitfetch('/api/certificate-info-upload',{method:'POST',body:formData})constresult=awaitresponse.json()if(result.status!=='ok'){setError(result.message,result.message)return}resultData.value=result.data}catch(error:any){setError('REQUEST_FAILED',error?.message)}}

结果数据格式化与下载能力

为了让证书信息更易读,页面做了多层格式化封装:

  • formatValue负责通用的字符串和数组转展示文本,空值统一显示为-
  • formatKeyUsageformatExtKeyUsage会把枚举值数组映射成带中文说明的字符串;
  • formatBasicConstraints把 CA 标志和路径长度组合成人类可读的描述。

下载能力则由downloadCertificate()downloadPublicKey()两个函数提供:

  • 首先检查resultData.downloads中是否存在对应的 PEM 内容,不存在则弹出下载不可用提示;
  • 然后使用sanitizeFileName()基于证书主题中的commonName生成安全的文件名;
  • 最后通过downloadText(content, filename)封装 Blob、创建临时链接并触发浏览器下载。

整体来看,这个 Vue3 实现把「输入 → 校验 → 请求 → 渲染结果 → 下载」整条链路拆分成若干职责清晰的小函数,既方便前端页面维护,也为后续扩展更多证书相关工具打好了基础。

constformatValue=(value:unknown)=>{if(Array.isArray(value)){returnvalue.length?value.join('\n'):'-'}if(value===null||value===undefined||value===''){return'-'}returnString(value)}constformatCertValue=(key:string)=>{constvalue=resultData.value?.certInfo?.[key]if(key==='keyUsage')returnformatKeyUsage(value)if(key==='extendedKeyUsage')returnformatExtKeyUsage(value)if(key==='basicConstraints')returnformatBasicConstraints(value)if(key==='publicKeySize'&&value){returnt('certificateInfoViewer.result.bits',{value})}returnformatValue(value)}constdownloadText=(content:string,filename:string)=>{constblob=newBlob([content],{type:'application/x-pem-file'})consturl=URL.createObjectURL(blob)constlink=document.createElement('a')link.href=url link.download=filename link.click()URL.revokeObjectURL(url)}constdownloadCertificate=()=>{if(!resultData.value?.downloads?.certPem){notify(t('certificateInfoViewer.messages.downloadUnavailable'),'warning')return}constcn=sanitizeFileName(resultData.value?.subjectInfo?.commonName||'')constfilename=cn?`${cn}.pem`:'certificate.pem'downloadText(resultData.value.downloads.certPem,filename)}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 11:05:07

CCMusic跨平台开发:Windows与Linux部署对比

CCMusic跨平台开发&#xff1a;Windows与Linux部署对比 如果你正在开发一个音乐相关的AI应用&#xff0c;或者想在自己的项目中集成音乐风格识别功能&#xff0c;那么CCMusic的音乐流派分类模型可能正是你需要的。不过&#xff0c;当你准备部署这个模型时&#xff0c;可能会遇…

作者头像 李华
网站建设 2026/4/16 11:02:03

零门槛搭建全场景覆盖的个人串流服务器:Sunshine从入门到精通

零门槛搭建全场景覆盖的个人串流服务器&#xff1a;Sunshine从入门到精通 【免费下载链接】Sunshine Sunshine: Sunshine是一个自托管的游戏流媒体服务器&#xff0c;支持通过Moonlight在各种设备上进行低延迟的游戏串流。 项目地址: https://gitcode.com/GitHub_Trending/su…

作者头像 李华
网站建设 2026/4/16 12:44:48

EasyAnimateV5-7b-zh-InP实测:中文提示词生成高清视频

EasyAnimateV5-7b-zh-InP实测&#xff1a;中文提示词生成高清视频 最近在测试各种视频生成模型时&#xff0c;我发现了EasyAnimateV5-7b-zh-InP这个镜像。作为一个专门针对中文提示词优化的图生视频模型&#xff0c;它号称能用简单的几句话就生成6秒的高清动态视频。这听起来很…

作者头像 李华
网站建设 2026/4/16 12:13:52

AI头像生成器入门指南:从零开始搭建开发环境

AI头像生成器入门指南&#xff1a;从零开始搭建开发环境 想自己动手做一个AI头像生成器吗&#xff1f;看着网上那些一键生成卡通头像、职业照的工具&#xff0c;是不是觉得挺神奇的&#xff1f;其实&#xff0c;搭建一个属于自己的AI头像生成环境&#xff0c;并没有想象中那么…

作者头像 李华
网站建设 2026/4/16 11:00:44

万象熔炉 | Anything XL开源镜像:纯本地推理无网络依赖部署教程

万象熔炉 | Anything XL开源镜像&#xff1a;纯本地推理无网络依赖部署教程 1. 开篇&#xff1a;为什么选择本地图像生成工具 你是不是经常遇到这样的情况&#xff1a;想用AI生成一些好看的二次元图片&#xff0c;但网上的在线工具要么要收费&#xff0c;要么生成质量不稳定&…

作者头像 李华
网站建设 2026/4/16 12:51:53

计算机图形学:基于Shader的实时旋转判断

计算机图形学&#xff1a;基于Shader的实时旋转判断 1. 引言 你有没有遇到过这样的情况&#xff1a;在手机上查看照片时&#xff0c;发现图片方向不对&#xff0c;需要手动旋转才能正常观看&#xff1f;或者在使用图像处理软件时&#xff0c;需要自动识别并校正图片的方向&am…

作者头像 李华