欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Electron 引用本地图片 安全问题及解决

程序员文章站 2022-03-13 17:29:25
Electron 引用本地图片 发现的问题及解决问题描述定位错误分析问题解决问题结果问题描述YouComic Studio 开源项目是基于Electron + umijs + Typescript进行的开发。由于Electron早起版本会有一定的安全性问题,我收到了Github bot自动检查并提出的安全性修复pull request于是开始着手升级Electron以及相关的依赖。但是却到了一些问题,例如更新之后无法在Renderer内直接引用本地图片。出现了下面的问题:原来卡片中应显示图片,...

Electron 引用本地图片 发现的问题及解决

问题描述

YouComic Studio 开源项目是基于Electron + umijs + Typescript进行的开发。

由于Electron早起版本会有一定的安全性问题,我收到了Github bot自动检查并提出的安全性修复pull request
Electron 引用本地图片 安全问题及解决
于是开始着手升级Electron以及相关的依赖。但是却到了一些问题,例如更新之后无法在Renderer内直接引用本地图片。出现了下面的问题:
Electron 引用本地图片 安全问题及解决
原来卡片中应显示图片,但是图片缺无法加载。

定位错误

首先先从Console找到问题所在:
Electron 引用本地图片 安全问题及解决
提示的错误是

net::ERR_UNKNOWN_URL_SCHEME

看来是Scheme的问题,查看图片的请求地址为:

file:///C:/Users/takayamaaren/xxx/xxx/xxxx/cover.jpg

将问题的关键锁定在scheme上,即file:///出了问题。

分析问题

这是由于Electron升级所带来的问题,原因是低版本(Electron 4.x)以下的版本存在着一定的安全问题,在4升级至5的版本中加入了更多的安全特性。

在这个Stack Overflow `Electron JS Images from Local File System问题中提到了这个错误

Electron by default allows local resources to be accessed by render processes only when their html files are loaded from local sources with the file:// protocol for security reasons.
If you are loading the html from any http:// or https:// protocol even from a local server like webpack-dev-server, access to local resources is disabled.
If you loading html pages from a local server only during development and switching to local html files in production, you can disable websecurity during development, taking care to enable it in production.
If you are loading html from remote sources even in production, the best and secure way is to upload it somewhere on your server and load it.

简而言之就是Electron因为安全问题无法直接访问本地文件,通过file:///

解决问题

如果出现了图中的 Not allowed to load local resource错误
Electron 引用本地图片 安全问题及解决
可以将webSecurity改为设置为false

webPreferences: {
	...
    webSecurity: false,
      
 }

查看Electron官方文档,找到有关于Protocol的内容,官方的example为:

const { app, protocol } = require('electron')
const path = require('path')

app.whenReady().then(() => {
	//注册FileProtocol
  protocol.registerFileProtocol('atom', (request, callback) => {
  	//截取file:///之后的内容,也就是我们需要的
    const url = request.url.substr(8)
    //使用callback获取真正指向内容
    callback({ path: path.normalize(`${__dirname}/${url}`) })
  }, (error) => {
    if (error) console.error('Failed to register protocol')
  })
})

从示例可以观察出,我们事先需要指定某一个Scheme为文件的Scheme,在这里不一定需要file:///作为Scheme,你也可以使用自定的Scheme例如:youcomic:///,示例中使用的是atom:///

在函数中你可以做一些特殊处理,其作用类似于拦截器原理。

我们将实际代码修改为:

protocol.interceptFileProtocol('file', (req, callback) => {
    const url = req.url.substr(8);
    callback(slash(decodeURI(url)));
  }, (error) => {
    if (error) {
      console.error('Failed to register protocol');
    }
  });

这里有几个要注意的地方:

  1. url是encode过的,需要使用decodeURI
  2. 由于文件系统的问题,可能需要slash进行\与·/的处理,否则可能无法访问。

结果

修改完成之后Electron可以正常显示图片
Electron 引用本地图片 安全问题及解决

本文地址:https://blog.csdn.net/Takayamaaren/article/details/107289994