使用HTTPS 服务在浏览器端使用摄像头的方式解析

1.方式1

// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import basicSsl from '@vitejs/plugin-basic-ssl'export default defineConfig({plugins: [vue(),basicSsl({name: 'test',domains: ['192.168.15.166', 'localhost'], // 添加您的IPcertDir: './cert',}),],server: {host: '0.0.0.0',port: 3000,https: true,proxy: {'/api': {target: 'http://localhost:5000',changeOrigin: true,},},},build: {outDir: 'dist',assetsDir: 'assets',sourcemap: false,minify: 'terser',rollupOptions: {output: {chunkFileNames: 'js/[name]-[hash].js',entryFileNames: 'js/[name]-[hash].js',assetFileNames: '[ext]/[name]-[hash].[ext]',},},},
})

2.方式2

// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import fs from 'fs'
import path from 'path'export default defineConfig({plugins: [vue(),],server: {https: {key: fs.readFileSync(path.resolve(__dirname, 'cert/key.pem')),cert: fs.readFileSync(path.resolve(__dirname, 'cert/cert.pem'))},host: '0.0.0.0',port: 3000,proxy: {'/api': {target: 'http://localhost:5000',changeOrigin: true},},},build: {outDir: 'dist',assetsDir: 'assets',sourcemap: false,minify: 'terser',},
})

这两个 Vite 配置文件都实现了 HTTPS 服务,这是浏览器访问摄像头等敏感设备的必要条件。以下详细解释它们的原理和差异。

为什么需要 HTTPS

现代浏览器出于安全考虑,要求在以下情况下才能访问摄像头、麦克风等敏感设备:

  • 使用 HTTPS 协议(安全连接)
  • 或者是 localhost 域名(本地开发特例)

这是因为 getUserMedia() API 被归类为"强大功能"(Powerful Features),需要安全上下文(Secure Context)。

方式一:使用 @vitejs/plugin-basic-ssl 插件

plugins: [vue(),basicSsl({name: 'test',domains: ['192.168.31.179', 'localhost'],certDir: './cert',}),
]

原理:

  1. 自动生成证书:插件会自动为指定的域名生成自签名 SSL 证书
  2. 证书存储:生成的证书存储在 ./cert 目录中
  3. 多域名支持:可以为多个域名/IP 生成证书(如局域网 IP 和 localhost)
  4. 自动配置:插件会自动将证书配置到 Vite 的 HTTPS 服务器

工作流程:

  • 首次运行时,插件检查证书是否存在
  • 如果不存在,使用内置的证书生成器创建自签名证书
  • 将证书自动注入到 Vite 的 server 配置中
  • 后续运行时复用已生成的证书

方式二:手动配置证书

server: {https: {key: fs.readFileSync(path.resolve(__dirname, 'cert/key.pem')),cert: fs.readFileSync(path.resolve(__dirname, 'cert/cert.pem'))},
}

原理:

  1. 手动管理证书:需要预先生成或获取 SSL 证书文件
  2. 文件读取:使用 Node.js 的 fs 模块直接读取证书文件
  3. 直接配置:将证书内容直接传递给 Vite 的 HTTPS 配置

证书生成方式(通常使用 OpenSSL):

# 生成私钥
openssl genrsa -out key.pem 2048
# 生成证书
openssl req -new -x509 -key key.pem -out cert.pem -days 365

关键差异对比

特性方式一(plugin-basic-ssl)方式二(手动配置)
便利性高 - 自动生成和管理低 - 需要手动创建证书
灵活性中等 - 插件预设配置高 - 完全自定义
证书类型自签名证书可以使用任何证书(自签名或CA签发)
多域名支持内置支持,配置简单需要生成包含 SAN 的证书
首次设置零配置,自动完成需要手动生成证书
团队协作每个开发者自动生成需要共享证书文件
证书更新删除旧证书即可重新生成手动重新生成和替换
依赖性需要安装额外插件仅需 Node.js 内置模块

实际应用场景

方式一适合:

  • 本地开发环境
  • 快速原型开发
  • 需要在局域网内多设备测试
  • 团队成员各自开发,不共享证书

方式二适合:

  • 需要使用特定证书(如公司内部 CA 签发)
  • 生产环境的本地模拟
  • 需要精确控制证书配置
  • 已有证书管理流程的团队

浏览器访问摄像头的实现

无论使用哪种方式,配置 HTTPS 后都可以使用以下代码访问摄像头:

navigator.mediaDevices.getUserMedia({ video: true, audio: true 
})
.then(stream => {// 获取到媒体流videoElement.srcObject = stream;
})
.catch(err => {console.error('无法访问摄像头:', err);
});

注意事项

  1. 证书信任:两种方式生成的自签名证书都会导致浏览器警告,需要手动信任
  2. 局域网访问:方式一通过配置 IP 地址,可以让局域网内其他设备通过 HTTPS 访问
  3. 安全性:这些配置仅适用于开发环境,生产环境应使用正规 CA 签发的证书

总的来说,方式一更适合快速开发和原型验证,方式二则提供了更多的控制权和灵活性。选择哪种方式主要取决于项目需求和团队的技术偏好。

这是使用自签名证书进行本地开发时的常见问题。让我详细说明解决方案:

一、手机无法访问的问题排查

1. 确保网络连通性

// vite.config.js
server: {host: '0.0.0.0',  // 允许外部访问port: 3000,https: true,
}

检查步骤:

  • 确保手机和电脑在同一局域网
  • 电脑防火墙允许 3000 端口
  • 使用电脑的局域网 IP(如 https://192.168.31.179:3000

2. 防火墙设置

# Windows - 以管理员运行
netsh advfirewall firewall add rule name="Vite Dev Server" dir=in action=allow protocol=TCP localport=3000# macOS
sudo pfctl -d  # 临时关闭防火墙测试# Linux
sudo ufw allow 3000/tcp

二、手机端安装证书的正确方法

iOS 设备

  1. 生成包含正确信息的证书:
# 创建证书配置文件 cert.conf
cat > cert.conf <<EOF
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no[req_distinguished_name]
C = CN
ST = State
L = City
O = Organization
CN = 192.168.31.179[v3_req]
keyUsage = critical, digitalSignature, keyAgreement
extendedKeyUsage = serverAuth
subjectAltName = @alt_names[alt_names]
DNS.1 = localhost
IP.1 = 192.168.31.179
IP.2 = 127.0.0.1
EOF# 生成证书
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \-keyout key.pem -out cert.pem -config cert.conf
  1. 安装证书到 iOS:
  • cert.pem 文件通过邮件/AirDrop 发送到手机
  • 点击证书文件,选择"安装"
  • 设置 → 通用 → 关于本机 → 证书信任设置
  • 开启对该证书的完全信任

Android 设备

  1. Android 安装步骤:
  • cert.pem 重命名为 cert.crt
  • 传输到手机
  • 设置 → 安全 → 加密与凭据 → 安装证书 → CA 证书
  • 选择证书文件安装

三、使用 mkcert 工具(推荐方案)

mkcert 可以创建本地受信任的证书,避免所有警告:

安装 mkcert

# Windows (使用 Chocolatey)
choco install mkcert# macOS
brew install mkcert# Linux
apt install libnss3-tools
wget -O mkcert https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-amd64
chmod +x mkcert
sudo mv mkcert /usr/local/bin/

配置本地 CA 并生成证书

# 1. 安装本地 CA
mkcert -install# 2. 生成证书(包含所有需要的域名和 IP)
mkcert -cert-file cert.pem -key-file key.pem localhost 127.0.0.1 192.168.31.179 ::1# 3. 为手机生成 CA 证书
mkcert -CAROOT  # 显示 CA 证书位置

更新 Vite 配置

// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import fs from 'fs'
import path from 'path'export default defineConfig({plugins: [vue()],server: {https: {key: fs.readFileSync('./key.pem'),cert: fs.readFileSync('./cert.pem')},host: '0.0.0.0',port: 3000,}
})

手机端信任 mkcert CA

  1. 获取 CA 证书:
# 找到 CA 证书位置
mkcert -CAROOT
# 通常在: 
# Windows: %LOCALAPPDATA%\mkcert
# macOS: ~/Library/Application Support/mkcert
# Linux: ~/.local/share/mkcert
  1. rootCA.pem 发送到手机并安装

四、使用 ngrok(外网访问方案)

如果证书问题难以解决,可以使用 ngrok 提供的 HTTPS 隧道:

# 安装 ngrok
npm install -g ngrok# 启动本地服务后,创建隧道
ngrok http 3000# 会得到类似这样的地址:
# https://abc123.ngrok.io

优点:

  • 自动 HTTPS,无需证书配置
  • 可以外网访问
  • 手机无需安装证书

五、开发环境最佳实践配置##

// vite.config.js - 完整的 HTTPS 配置方案
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import fs from 'fs'
import path from 'path'
import { execSync } from 'child_process'// 获取本机局域网 IP
function getLocalIP() {const os = require('os')const interfaces = os.networkInterfaces()for (const name of Object.keys(interfaces)) {for (const iface of interfaces[name]) {if (iface.family === 'IPv4' && !iface.internal) {return iface.address}}}return '127.0.0.1'
}// 自动生成证书函数
function ensureCertificates() {const certDir = path.resolve(__dirname, 'cert')const keyPath = path.join(certDir, 'key.pem')const certPath = path.join(certDir, 'cert.pem')// 检查证书是否存在if (fs.existsSync(keyPath) && fs.existsSync(certPath)) {console.log('✅ 使用现有证书')return { key: keyPath, cert: certPath }}// 创建证书目录if (!fs.existsSync(certDir)) {fs.mkdirSync(certDir, { recursive: true })}const localIP = getLocalIP()console.log(`📱 局域网 IP: ${localIP}`)// 检查是否安装了 mkcerttry {execSync('mkcert -version', { stdio: 'ignore' })console.log('🔧 使用 mkcert 生成受信任的证书...')// 安装本地 CA(如果还没安装)execSync('mkcert -install', { stdio: 'inherit' })// 生成证书execSync(`mkcert -cert-file ${certPath} -key-file ${keyPath} localhost 127.0.0.1 ${localIP} ::1`,{ stdio: 'inherit' })console.log('✅ mkcert 证书生成成功!')console.log('📱 手机端请安装 CA 证书:')const caRoot = execSync('mkcert -CAROOT').toString().trim()console.log(`   ${path.join(caRoot, 'rootCA.pem')}`)} catch (e) {console.log('⚠️  mkcert 未安装,使用 OpenSSL 生成自签名证书...')// 创建 OpenSSL 配置const configPath = path.join(certDir, 'openssl.cnf')const opensslConfig = `
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no[req_distinguished_name]
C = CN
ST = State
L = City
O = Dev Organization
CN = ${localIP}[v3_req]
keyUsage = critical, digitalSignature, keyAgreement
extendedKeyUsage = serverAuth
subjectAltName = @alt_names[alt_names]
DNS.1 = localhost
DNS.2 = *.localhost
IP.1 = 127.0.0.1
IP.2 = ${localIP}
IP.3 = ::1
`fs.writeFileSync(configPath, opensslConfig)// 生成证书try {execSync(`openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${keyPath} -out ${certPath} -config ${configPath}`,{ stdio: 'inherit' })console.log('✅ 自签名证书生成成功!')console.log('⚠️  浏览器会显示安全警告,需要手动信任证书')} catch (error) {console.error('❌ 证书生成失败:', error)process.exit(1)}}return { key: keyPath, cert: certPath }
}// 生成或获取证书
const certificates = ensureCertificates()export default defineConfig({plugins: [vue()],server: {https: {key: fs.readFileSync(certificates.key),cert: fs.readFileSync(certificates.cert)},host: '0.0.0.0',  // 允许外部访问port: 3000,// 显示二维码方便手机扫描open: false,// 配置 CORScors: true,// 代理配置proxy: {'/api': {target: 'http://localhost:5000',changeOrigin: true,secure: false,}}},// 构建配置build: {outDir: 'dist',assetsDir: 'assets',sourcemap: false,minify: 'terser',rollupOptions: {output: {chunkFileNames: 'js/[name]-[hash].js',entryFileNames: 'js/[name]-[hash].js',assetFileNames: '[ext]/[name]-[hash].[ext]',}}},// 优化配置optimizeDeps: {exclude: ['vue']}
})// 启动后打印访问信息
process.nextTick(() => {const localIP = getLocalIP()console.log('\n🚀 服务已启动:')console.log(`   本地: https://localhost:3000`)console.log(`   局域网: https://${localIP}:3000`)console.log('\n📱 手机访问提示:')console.log('   1. 确保手机与电脑在同一 WiFi')console.log('   2. 如有证书警告,点击"高级"→"继续访问"')console.log('   3. iOS 需在"设置"→"通用"→"关于本机"→"证书信任设置"中信任证书\n')
})

六、配套的 package.json 脚本

{"scripts": {"dev": "vite","dev:host": "vite --host","dev:network": "vite --host 0.0.0.0","dev:https": "node scripts/setup-https.js && vite","cert:install": "mkcert -install","cert:generate": "mkcert -cert-file cert/cert.pem -key-file cert/key.pem localhost 127.0.0.1 $(ipconfig getifaddr en0 || hostname -I | awk '{print $1}') ::1","cert:trust": "mkcert -install && npm run cert:generate","build": "vite build","preview": "vite preview","tunnel": "ngrok http 3000"},"devDependencies": {"@vitejs/plugin-basic-ssl": "^1.0.1","@vitejs/plugin-vue": "^4.2.3","vite": "^4.3.9","vue": "^3.3.4"},"dependencies": {"qrcode": "^1.5.3"}
}

七、快速解决方案总结

最简单的方案(推荐)

  1. 安装 mkcert
# 一次性设置,永久解决证书问题
brew install mkcert  # macOS
mkcert -install
  1. 生成证书
mkcert -cert-file cert.pem -key-file key.pem localhost 192.168.xxx.xxx
  1. 手机端信任
  • ~/.local/share/mkcert/rootCA.pem(或对应系统路径)发送到手机
  • 安装为受信任的 CA 证书

故障排查清单

网络连接

  • 手机和电脑同一 WiFi?
  • 防火墙允许 3000 端口?
  • 使用正确的 IP 地址?

证书配置

  • 证书包含局域网 IP?
  • 证书已安装到手机?
  • iOS 已在"证书信任设置"中启用?

Vite 配置

  • host: '0.0.0.0' 已设置?
  • https: true 或手动配置证书?
  • 端口没有被占用?

终极备用方案

如果以上都不行,使用 localtunnelngrok

npx localtunnel --port 3000 --subdomain myapp
# 或
ngrok http 3000

这样可以获得一个临时的公网 HTTPS 地址,无需任何证书配置,手机可以直接访问。

主要缺点是需要依赖外部服务,并且速度可能较慢。但对于紧急测试和演示,这是最快的解决方案。

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

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

相关文章

上下文管理器和异步I/O

目录 一、上下文管理器 1.1 定义 1.2 特点 1.3 适用场景 1.4 具体实现 1.5 具体实例 1.5.1 文件管理器 1.5.2 线程锁释放资源 二、异步I/O 2.1 定义 2.2 特点 2.3 实现方式 2.4 适用场景 高并发网络服务&#xff1a;Web服务器、API服务等需要处理大量并发连接 2…

LabVIEW信号监测与分析

借助 LabVIEW 平台&#xff0c;生成含正弦波与噪声的信号&#xff0c;经频谱分析等处理&#xff0c;结合动态限值判断信号是否超限&#xff0c;广泛用于音频、振动等领域的信号监测&#xff0c;助力高效开展信号分析与质量把控。概念说明系统围绕信号的生成、处理、分析及监测展…

MySQL数据库与表的创建、修改及数据操作指南

精选专栏链接 &#x1f517; MySQL技术笔记专栏Redis技术笔记专栏大模型搭建专栏Python学习笔记专栏深度学习算法专栏 欢迎订阅&#xff0c;点赞&#xff0b;关注&#xff0c;每日精进1%&#xff0c;与百万开发者共攀技术珠峰 更多内容持续更新中&#xff01;希望能给大家带来…

​new species of flying reptile1 discovered in Scotland​

Pterosaur: new species of flying reptile1 discovered in Scotland 苏格兰斯凯岛发现新翼龙物种 考古学家们在苏格兰斯凯岛发现了一个新的翼龙物种。这种独特的飞行爬行动物生活在1.68 – 1.66亿年前。 This flying reptile soared over the heads of dinosaurs2 when Scotla…

03 节点行为

审批流程图如下图&#xff0c;在此流程图中&#xff0c;存在两个UserTask节点&#xff0c;第一个节点是主管审批&#xff0c;第二个节点是产品经理审批&#xff0c;两个节点中间有一个排他网关&#xff0c;此网关用来对主管审批的结果进行判断&#xff0c;如果主管审批通过&…

深度卷积生成对抗网络详解与实现

深度卷积生成对抗网络详解与实现 0. 前言 1. 网络架构 1.1 批归一化 1.2 激活 1.3 上采样 2. 构建 DCGAN 2.1 生成器 2.2 判别器 2.3 训练 DCGAN 0. 前言 深度卷积生成对抗网络 (Deep Convolutional Generative Adversarial Network, DCGAN) 是基于生成对抗网络 (Generative A…

CF607B Zuma -提高+/省选-

CF607B Zuma codeforces 原链接 题目描述 Genos\texttt{Genos}Genos 最近在他的手机上下载了祖玛游戏。在祖玛游戏里&#xff0c;存在 nnn 个一行的宝石&#xff0c;第 iii 个宝石的颜色是 CiC_iCi​。这个游戏的目标是尽快的消灭一行中所有的宝石。 在一秒钟&#xff0c;Ge…

拆分了解HashMap的数据结构

文章目录 前言 一、底层数据结构总览 二、核心组成部分详解 1. 数组&#xff08;哈希表&#xff09; 2. 节点&#xff08;Node&#xff09; 3. 红黑树&#xff08;TreeNode&#xff09; 三、哈希函数与索引计算 四、哈希冲突的解决 五、扩容机制 六、关键特性与注意事…

关于电脑连接不到5g的WiFi时的一些解决办法

方法一、设备管理器重卸载驱动后&#xff0c;重装驱动。方法二、打开控制面板 “控制面板\网络和 Internet\网络连接” &#xff08;亲测有效&#xff09;点击更改适配器配置右击当前的WLAN属性点击配置选择“高级” 802.11a/b/g 无线模式选项栏 值&#xff1a;6.的双…

Mathtype公式批量编号一键设置公式居中编号右对齐

插件[ygtools] 批量编号一键设置公式居中编号右对齐 单栏/多栏均可https://wwon.lanzout.com/i0NRf35vyw8j 下载密码8543

基于ssm的小橘子出行客户体验评价系统[SSM]-计算机毕业设计源码+LW文档

摘要&#xff1a;随着出行行业的快速发展&#xff0c;客户体验评价对于出行服务质量的提升至关重要。本文设计并实现了基于SSM&#xff08;Spring Spring MVC MyBatis&#xff09;框架的小橘子出行客户体验评价系统。该系统涵盖系统用户管理、司机信息管理、客户评价管理等功…

算法日记---二分查找

目录 前言 一、二分查找 1.思想 2.简单二分 3.优点 4.局限性 二、模板 1.基本模板 2.简单例题&#xff08;LeetCode&#xff09; 4.有重复元素的二分 5.0-1问题 总结 前言 本文通过讲解简单的二分查找配合leetcode例题对二分查找本质、模板进行了基础的总结 提示&a…

Level Set(水平集)算法——形象化讲解

目录 维度一&#xff1a;核心思想与比喻&#xff08;它像什么&#xff1f;&#xff09; 维度二&#xff1a;要解决什么问题&#xff1f;&#xff08;它能干嘛&#xff1f;有什么用&#xff1f;&#xff09; 维度三&#xff1a;工作原理&#xff08;它是怎么做到的&#xff1…

DDoS 攻防“军备竞赛”的幕后

谈到 DDoS&#xff08;分布式拒绝服务攻击&#xff09;&#xff0c;很多人会想到“黑客租用肉鸡发流量&#xff0c;网站直接崩”。但事实上&#xff0c;如今的 DDoS 攻防早已变成一场 军备竞赛。攻击者的武器越来越“工业化”&#xff1a;僵尸网络商品化&#xff1a;黑市上&…

如何用 Rust 重写 SQLite 数据库(二):是否有市场空间?

用 Rust 实现一个类似 SQLite 的嵌入式数据库非常有意义&#xff0c;但需要结合具体目标和场景来评估其价值。以下从技术、生态、市场需求和个人成长等多个维度展开分析&#xff0c;并给出结论。一、技术价值&#xff1a;Rust 与数据库的天然契合 SQLite 作为全球装机量最大的数…

【Web】ImaginaryCTF 2025 wp

目录 imaginary-notes certificate codenames-1 passwordless pearl imaginary-notes I made a new note taking app using Supabase! Its so secure, I put my flag as the password to the "admin" account. I even put my anonymous key somewhere in the si…

oracel如何找到外键子表

要找到导致外键约束冲突的子表&#xff08;即包含"child record"的表&#xff09;&#xff0c;可以通过以下SQL查询在Oracle数据库中定位&#xff1a;1. 查询约束基本信息&#xff08;确定父表和子表&#xff09;SELECT owner, constraint_name, table_name AS child…

智源研究院新研究:突破物理世界智能边界的RoboBrain 2.0,将重构具身AI能力天花板

当你对着家用机器人说"把杯子放在笔筒和键盘之间&#xff0c;对齐杯身logo"时&#xff0c;它能精准理解空间关系并执行动作&#xff1b;当多台机器人在超市协作补货时&#xff0c;它们能自主规划轨迹、避免冲突并完成长周期任务——这些曾经出现在科幻电影中的场景&a…

【2025】Office核心组件Microsoft word,Excel,PowerPoint详细使用指南

Office 核心组件使用指南 Microsoft Word 文字处理 Word主要用于创建和编辑文档&#xff0c;如信件、报告、论文等。 2025Office&#x1f517; 1. 界面认识 快速访问工具栏&#xff1a;位于左上角&#xff0c;可自定义保存、撤销、恢复等常用命令。功能区&#xff1a;顶部…

【模型训练篇】VeRL的使用 - RL(PPO)与源码

继续学习字节家的VeRL&#xff0c;今天来看看VeRL的RL&#xff0c;是VeRL系列的第三篇文章&#xff08;话说近期好多大事儿&#xff0c;我司发布了Longcat、韩立结婴、阿里周五发布了QWen-Next都是好东西啊&#xff0c;学不过来了damn&#xff09; 底层分布式能力基础Ray&…