Electron callback can only be called for once

2020-04-17 04:39发布

问题:

I have a simple electron app that wraps around a web app that prompts for username and password.

Problems:

1) When the user inputs the wrong credentials and the authWindow appears again. With the right credentials the second time login does not happen.

2) When the user inputs the wrong credentials twice, the authWindow no longer appears.

Any help is appreciated.

Here is my code:

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

app.on("login", (event, webContents, request, authInfo, callback) => {
  event.preventDefault();

  createAuthWindow().then(credentials => {
    callback(credentials.username, credentials.password);
  });
});

function createAuthWindow() {
  authWindow = new BrowserWindow({
    show: false,
    width: 400, 
    height: 200, 
    webPreferences: {
      nodeIntegration: true
    },
    title: "Authentication",
  });

  authWindow.on('ready-to-show', function (){
    authWindow.show();
  });

  authWindow.loadFile('password-form.html');

  return new Promise((resolve, reject) => {
    ipcMain.once('password-form-submission', (event, username, password) => {
      authWindow.close();
      const credentials = {
        username,
        password
      };
      resolve(credentials);
    });
  });
}

function createChatWindow() {
    chatWindow = new BrowserWindow({
        show: false,
        width: 1000, 
        height: 800, 
        webPreferences: {
            devTools: true
        },
        icon: __dirname + '/build/icon.png',
        title: "Messenger",
    });

    chatWindow.once('ready-to-show', function (){
      chatWindow.show();
    });

    chatWindow.loadURL('https://example.com');
    chatWindow.webContents.openDevTools();
}

app.on('ready', createChatWindow);

回答1:

Update: In Electron 8, this issue seems to be resolved so you don't need to do the workaround described below.

I've faced this issue as well and here's what I ended up doing...

I've had to use this Electron ClientRequest api to be able to retry more times.

Your "login" event handler will look something like this

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

app.on("login", (event, webContents, request, authInfo, callback) => {
  event.preventDefault();

  let username = "";
  let password = "";

  const req = net.request({
    method: request.method,
    url: request.url
  });

  req.on("response", response => {
    console.log(response);
    if (response.statusCode > 400) {
      console.error("something went wrong");
      callback("", "");
    } else {
      console.log("we are good, request was successful"); // the request was authenticated correctly
      callback(username, password);
    }
    response.on("error", err => {
      console.error("something went wrong, response error", err);
      callback("", "");
    });
  });

  req.on("login", (loginAuthInfo, loginCallback) => {
    this.createAuthPrompt().then(credentials => {
      username = credentials.username;
      password = credentials.password;
      loginCallback(username, password);
    });
  });

  req.end();
});


标签: electron