You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Electron应用使用IndexedDB实现登录时出现Invalid security origin错误

Electron登录页面IndexedDB验证问题修复

问题描述

我正在为Electron Web应用开发登录/注册页面,仅使用JavaScript、HTML和CSS,通过IndexedDB存储用户凭证。在Electron窗口的开发者工具Application面板中可确认用户名和密码已成功保存,但用户尝试登录时出现以下错误:
Request CacheStorage.requestCacheNames failed. {"code":-32602,"message":"Invalid security origin"}
同时用户会被重定向到空白页面,添加的console.log语句也没有任何输出,尝试添加console.log和alert打印登录信息也无效。

错误根源分析

  1. 登录表单未绑定提交事件:点击登录按钮后,表单默认执行提交动作,页面直接跳转,导致验证逻辑根本没机会执行。
  2. 登录验证函数存在多处错误:
    • 函数名e与事件对象重名,导致逻辑混乱
    • 未定义key变量就直接用于索引查询
    • IndexedDB的users对象库未创建email索引,却直接调用store.index('email')
    • window.location.replace(homepage.html)语法错误,目标路径未加引号
  3. Electron本地文件协议限制:使用file://协议加载页面时,浏览器安全策略会限制CacheStorage访问,触发Invalid security origin错误。

修复步骤

  • 为登录表单添加submit事件监听器,阻止默认跳转行为
  • 重构登录验证函数,修正命名、索引创建、变量定义和语法问题
  • 在Electron主进程中配置webPreferences,允许file协议的跨域和存储访问

修正后的代码

JavaScript代码

const signUpBtnLink = document.querySelector('.signUpBtn-link');
const signInBtnLink = document.querySelector('.signInBtn-link');
const wrapper = document.querySelector('.wrapper');

signUpBtnLink.addEventListener('click', () => {
    wrapper.classList.toggle('active');
});

signInBtnLink.addEventListener('click', () => {
    wrapper.classList.toggle('active');
});

let $ = document

const registerForm = $.querySelector(".form-wrapper-sign-up")
const loginForm = $.querySelector(".form-wrapper-sign-in form")
const nameInput = $.querySelector("#username")
const loginNameInput = $.querySelector("#username1")
const loginPasswordInput = $.querySelector("#password1")
const passwordInput = $.querySelector("#password")
const emailInput = $.querySelector("#email")
const table = $.querySelector("table")

let db = null
let objectStore = null

window.addEventListener("load", () => {
    let DBOpenRequest = indexedDB.open('DreamDB', 2)
    
    DBOpenRequest.addEventListener("error", err => {
        console.warn("DB Error: ", err)
    })
    DBOpenRequest.addEventListener("success", e => {
        db = e.target.result
        console.log("DB Success: ", e.target.result)
    })
    DBOpenRequest.addEventListener("upgradeneeded", e => {
        db = e.target.result
        
        console.log("DB Old Version: ", e.oldVersion)
        console.log("DB Upgraded: ", e)
        console.log("DB New Version: ", e.newVersion)
        
        let userStore;
        if(!db.objectStoreNames.contains("users")){
            userStore = db.createObjectStore('users', {
                keyPath: "userId"
            })
        } else {
            userStore = e.target.transaction.objectStore("users")
        }
        
        if (!userStore.indexNames.contains('email')) {
            userStore.createIndex('email', 'email', { unique: true });
        }
        
        if(db.objectStoreNames.contains("products")){
            db.deleteObjectStore('products')
        }
        
        console.log(db.objectStoreNames)
    })
})

registerForm.addEventListener("submit", e => {
    e.preventDefault()
    
    let newUserObj = {
        userId: Math.floor(Math.random() * 9999),
        name: nameInput.value,
        password: passwordInput.value,
        email: emailInput.value
    }
    
    let tx = createTransaction("users", "readwrite")
    tx.addEventListener("complete", e => {
        console.log("Write TX Complete: ", e)
    })
    
    let store = tx.objectStore("users")
    let req = store.add(newUserObj)
    
    req.addEventListener("error", err => {
        console.warn("Write REQ Error: ", err)
    })
    req.addEventListener("success", e => {
        console.log("Write REQ Success: ", e)
        clearInput()
    })
})

loginForm.addEventListener("submit", (e) => {
    e.preventDefault()
    const email = loginNameInput.value;
    const password = loginPasswordInput.value;
    
    if (!db) {
        alert("数据库未初始化,请刷新页面重试");
        return;
    }
    
    const tx = db.transaction(["users"], "readonly");
    const store = tx.objectStore("users");
    const emailIndex = store.index('email');
    const query = emailIndex.get(email);
    
    query.onsuccess = function() {
        if (query.result) {
            if (password === query.result.password) {
                console.log('登录成功');  
                alert(`欢迎登录,${query.result.name}`);
                window.location.replace('homepage.html');
            } else {
                alert("密码错误,请重新输入");
            }
        } else {
            alert("该邮箱未注册,请先注册");
        }
    };
    
    query.onerror = function(err) {
        console.warn("登录查询错误: ", err);
        alert("登录失败,请稍后重试");
    };
})

function getUser() {
    let tx = createTransaction("users", "readonly")
    tx.addEventListener("complete", e => {
        console.log("Get TX Complete: ", e)
    })
    
    let store = tx.objectStore("users")
    let req = store.getAll()
    
    req.addEventListener("error", err => {
        console.warn("Get REQ Error: ", err)
    })
    req.addEventListener("success", e => {
        console.log("Get REQ Success: ", e.target.result)
    })
}

function deleteUser(userId) {
    let tx = createTransaction("users", "readwrite")
    tx.addEventListener("complete", e => {
        console.log("Delete TX Complete: ", e)
    })
    
    let store = tx.objectStore("users")
    let req = store.delete(userId)
    
    req.addEventListener("error", err => {
        console.warn("Delete REQ Error: ", err)
    })
    req.addEventListener("success", e => {
        console.log("Delete REQ Success: ", e)
        getUser()
    })
}

function createTransaction(storeName, mode) {
    let tx = db.transaction(storeName, mode)
    tx.addEventListener("error", err => {
        console.warn("TX Error: ", err)
    })
    
    return tx
}

function clearInput() {
    nameInput.value = ''
    passwordInput.value = ''
    emailInput.value = ''
}

HTML代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Dream Mirror | Login</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css">
  <link rel="stylesheet" type="text/css" href="login.css">
</head>

<body>
  <h1><center>DREAM MIRROR</center> </h1>
  
  <div class="wrapper">
    <div class="form-wrapper sign-in">
      <form>
        <h2>Sign In</h2>
        <div class="input-group">
          <input id ="username1" type="text" placeholder="输入邮箱" required>
          <label for="">邮箱</label>
        </div>
        <div class="input-group">
          <input id = "password1" type="password" placeholder="输入密码" required>
          <label for="">Password</label>
        </div>
        <div class="remember">
          <label><input type="checkbox"> Remember me</label>
        </div>
        <button> Sign In</button>
        <div class="signUp-link">
          <p>Don't have an account? <a href="#" class="signUpBtn-link">Sign Up</a></p>
        </div>
        <div class="social-platform">
          <div class="social-icons"></div>
        </div>
      </form>
    </div>

    <div class="form-wrapper sign-up">
      <form class="form-wrapper-sign-up">
        <div id ="names"></div>
        <h2>Sign Up</h2>
        <div class="input-group">
          <input id="username" type="text" placeholder="输入用户名" required>
          <label for="">Username</label>
        </div>
        <div class="input-group">
          <input id="email" type="email" placeholder="输入邮箱" required>
          <label for="">Email</label>
        </div>
        <div class="input-group">
          <input id="password" type="password" placeholder="输入密码" required>
          <label for="">Password</label>
        </div>
        <div class="remember">
          <label><input type="checkbox"> I agree to the terms & conditions</label>
        </div>
        <button class="submit">Sign Up</button>
        <div class="signUp-link">
          <p>Already have an account? <a href="#" class="signInBtn-link">Sign In</a></p>
        </div>
      </form>
    </div>
  </div>

  <script defer src="login.js"></script>
</body>

</html>

CSS代码

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@100;200;400;700&display=swap');
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'poppins', sans-serif;
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  background: #808080;
  font-family: 'Poppins', sans-serif;
}

.wrapper {
  position: relative;
  width: 400px;
  height: 500px;
  background: rgba(255, 255, 255, .2);
  border-radius: 20px;
  box-shadow: 0 0 50px #fff;
  padding: 40px;
}

.form-wrapper {
  display: flex;
  align-items: center;
  width: 100%;
  height: 100%;
  transition: 1s ease-in-out;
}

.wrapper.active .form-wrapper.sign-in {
  transform: scale(0) translate(-300px, 500px);
}

.wrapper .form-wrapper.sign-up {
  position: absolute;
  top: 0;
  transform: scale(0) translate(200px, -500px);
}

.wrapper.active .form-wrapper.sign-up {
  transform: scale(1) translate(0, 0);
}

h2 {
  font-size: 30px;
  color: #fff;
  text-align: center;
  font-family: 'poppins' ,sans-serif;
}

.input-group {
  position: relative;
  margin: 30px 0;
  border-bottom: 2px solid #fff;
}

.input-group label {
  position: absolute;
  top: 50%;
  left: 5px;
  transform: translateY(-50%);
  font-size: 16px;
  color: #fff;
  pointer-events: none;
  transition: .5s;
  font-family: 'Poppins', sans-serif;
}

.input-group input {
  width: 320px;
  height: 40px;
  font-size: 16px;
  color: #fff;
  padding: 0 5px;
  background: transparent;
  border: none;
  outline: none;
  font-family: 'Poppins', sans-serif;
}

.input-group input:focus~label,
.input-group input:valid~label {
  top: -5px;
}

.remember {
  margin: -5px 0 15px 5px;
}

.remember label {
  color: #fff;
  font-size: 14px;
}

.remember label input {
  accent-color: #f4157e;
}

button {
  position: relative;
  width: 100%;
  height: 40px;
  background: #fff;
  font-size: 16px;
  color: #f4157e;
  cursor: pointer;
  border-radius: 30px;
  border: none;
  outline: none;
}

.signUp-link {
  font-size: 14px;
  text-align: center;
  margin: 15px 0;
}

.signUp-link p {
  color: #fff;
}

.signUp-link p a {
  color: #f4157e;
  text-decoration: none;
  font-weight: 500;
}

.signUp-link p a:hover {
  text-decoration: underline;
}

.social-platform {
  font-size: 14px;
  color: #fff;
  text-align: center;
}

.social-icons a {
  display: inline-block;
  width: 35px;
  height: 35px;
  background: transparent;
  border: 1px solid #fff;
  border-radius: 50%;
  text-align: center;
  line-height: 35px;
  margin: 15px 6px 0;
  transition: .3s;
}

.social-icons a:hover {
  background: #fff;
}

.social-icons a i {
  color: #fff;
  font-size: 14px;
  transition: .3s;
}

.social-icons a:hover i {
  color: rgba(0, 0, 0, .3);
}

h1{
  text-align: center;
  font-size: 45px;
  font-weight: 50;
  font-family: 'Poppins', sans-serif;
  position: absolute;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  color: white;
}

table {
  font-family: arial, sans-serif;
  border-collapse: collapse;
  width: 100%;
  margin-bottom: 50px;
}

td, th {
  border: 1px solid #dddddd;
  text-align: left;
  padding: 8px;
}

tr:nth-child(even) {
  background-color: #dddddd;
}

.text-center {
  text-align: center;
}

Electron主进程配置(解决安全origin错误)

const { app, BrowserWindow } = require('electron');

function createWindow() {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
      allowRunningInsecureContent: true,
      webSecurity: false
    }
  });

  mainWindow.loadFile('index.html');
  mainWindow.webContents.openDevTools();
}

app.whenReady().then(() => {
  createWindow();

  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit();
});

内容的提问来源于stack exchange,提问作者Sabrina D

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 23:18:09