Electron + xmpp.js:如何调试 SSL 自签名错误消息?
Electron + xmpp.js: How I can Debug SSL Self-signed error messages?
我正在使用 electron.js 和 xmpp.js 的组合来制作我自己的客户端。我的主要项目由这两个文件组成:
助推电子开启:index.js
:
const {app,BrowserWindow,ipcMain,dialog}=require('electron');
// const app=electron.app;
// const BrowserWindow=electron.BrowserWindow;
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) { // eslint-disable-line global-require
app.quit();
}
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
const createWindow = () => {
console.log("Message");
// Create the browser window.
mainWindow = new BrowserWindow();
// and load the index.html of the app.
mainWindow.loadURL(`file://${__dirname}/ui/index.html`);
var env = process.env.NODE_ENV || 'production';
if(env==='dev'){
// Open the DevTools.
mainWindow.webContents.openDevTools();
}
// Emitted when the window is closed.
mainWindow.on('closed', () => {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null;
});
mainWindow.maximize();
const xmpp=require('./xmpp.js');
console.log(xmpp)
xmpp.xmppCli(mainWindow,ipcMain,dialog);
};
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow();
}
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.
并用这个文件处理它 xmpp.js
:
const {client, xml, jid} = require('@xmpp/client')
var clientInstance=null;
console.log('xmpp.js loaded')
const initXmpp= function(xmpp){
xmpp.on('error', err => {
console.error("Error occured",err.toString())
dialog.showErrorBox('Internal Error',err.toString())
})
xmpp.on('offline', () => {
console.log('', 'offline')
})
xmpp.on('online', async address => {
dialog.showMessageBox({'type':'info','message':"Online as:"+address.toString()})
})
xmpp.on('stanza', stanza => {
console.log('⮈', stanza.toString())
xmpp.stop()
})
process.on('unhandledRejection', function (reason, p) {
console.log('Possibly Unhandled Rejection at: Promise ', p, ' reason: ', reason)
})
xmpp.start()
}
module.exports.xmppCli=function(mainWindow,ipcMain,dialog){
ipcMain.on('login',(event,params)=>{
let jidVal=jid(params.username);
params.server="xmpp://"+params.server
console.log(jidVal.getLocal(),jidVal.getDomain(),params.server)
if(!clientInstance){
console.log("Client Works");
try{
clientInstance=new client({
'service':params.server,
'domain': jidVal.getDomain(),
'username':jidVal.getLocal(),
'password':params.password,
})
initXmpp(clientInstance)
} catch(e) {
console.error('Internal Error',e.message)
console.error(e.stack)
clientInstance=null;
}
}
});
}
另外我的ui由index.html
组成:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Login Page</title>
<link rel="stylesheet" href="../../node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="../../node_modules/roboto-fontface/css/roboto/roboto-fontface.css">
<style>
html, body, .container-fluid {
height: 100%;
font-family: 'Roboto', sans-serif;
}
#form_wrapper{
border:1px solid;
border-radius: 10px;
}
</style>
<script>window.$ = window.jQuery = require('../../node_modules/jquery/dist/jquery.min.js');</script>
<script src="../../node_modules/jquery/dist/jquery.min.js"></script>
<script src="./index_renderer.js"></script>
</head>
<body class="bg-secondary">
<div class="container-fluid d-flex justify-content-center align-items-center">
<div id="form_wrapper" class="p-2" style="background-color:white;">
<h1 class="text-center">XMPP KEY AGREEMENT CLI</h1>
<form id="loginForm">
<div class="form-group">
<label for="server">XMPP Server</label>
<input id="server" class="form-control" type="text" name="server" placeholder="eg. example.com" required>
</div>
<div class="form-group">
<label for="username">Username</label>
<input id="username" class="form-control" type="text" name="username" placeholder="eg. user@example.com" required>
</div>
<div class="form-group">
<label for="password">Password</label>
<input id="password" class="form-control" type="text" name="password" placeholder="Type your password here" required>
</div>
<button type="submit" class="btn btn-primary btn-lg btn-block">Login</button>
</form>
</div>
</div>
</body>
</html>
使用以下渲染器:
$(document).ready(function(){
const ipcRenderer = require('electron').ipcRenderer;
$("#loginForm").on('submit',function(e){
e.preventDefault();
console.log("Form Submitted");
//
let data=$(this).serializeArray().reduce(function(a, x) { a[x.name] = x.value; return a; }, {});
ipcRenderer.send('login',data)
})
})
但我的问题是,当我使用自签名证书启动我自己的本地 opefireserver 时。因此,我得到了一个神秘的错误,显示如下:
所以我的问题是:
- 如何调试这些类型的错误?我的意思是我找不到这个错误的位置。
- 我如何手动告诉 electron 或 xmpp.js 手动接受自签名证书>
我试图通过更改手动找出此错误的产生位置:
xmpp.on('error', err => {
console.error("Error occured",err.toString())
dialog.showErrorBox('Internal Error',err.toString())
})
进入这个:
xmpp.on('error', err => {
console.error("Error occured",err.toString())
})
仍然出现奇怪的错误。
当发生连接错误时,@xmpp/client
库似乎缺少 api 调用,如下例所示:
const {client, xml, jid} = require('@xmpp/client')
const initXmpp=function(xmpp){
xmpp.on('error', err => {
console.error("Error occured",err.toString())
// dialog.showErrorBox('Internal Error',err.toString())
})
xmpp.on('offline', () => {
console.log('', 'offline')
})
xmpp.on('online', async address => {
dialog.showMessageBox({'type':'info','message':"Online as:"+address.toString()})
})
xmpp.on('stanza', stanza => {
console.log('⮈', stanza.toString())
xmpp.stop()
})
process.on('unhandledRejection', function (reason, p) {
console.error('Possibly Unhandled Rejection at: Promise ', p, ' reason: ', reason)
})
try{
xmpp.start()
} catch(e) {
console.error(e.message)
}
}
try{
clientInstance=new client({
'service':"xmpp://0.0.0.0:5222",
'domain': "example.com",
'username':"admin",
'password':"admin",
});
initXmpp(clientInstance);
} catch(e) {
console.error(e);
}
我收到以下错误:
events.js:183
throw er; // Unhandled 'error' event
^
Error: self signed certificate
at TLSSocket.<anonymous> (_tls_wrap.js:1105:38)
at emitNone (events.js:106:13)
at TLSSocket.emit (events.js:208:7)
at TLSSocket._finishInit (_tls_wrap.js:639:8)
at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:469:38)
并且没有提供任何方式来处理它,那是因为 SSL/TLS 连接是由 nodejs 本身处理的,因此唯一的解决方案可以在这个 gthub answer.
上找到
基于上面提到的解决方案实际上结合NODE_ENV
环境变量我将以下代码片段放在index.js
上:
if(env==='dev' || env=='debug'){
process.env.NODE_TLS_REJECT_UNAUTHORIZED=0;
}
另外,如果使用 this I would suggest to fork it and modify it to use latest version of ubuntu (or even a more stable docker image) and later version of openfire such as this 人的话。
我正在使用 electron.js 和 xmpp.js 的组合来制作我自己的客户端。我的主要项目由这两个文件组成:
助推电子开启:index.js
:
const {app,BrowserWindow,ipcMain,dialog}=require('electron');
// const app=electron.app;
// const BrowserWindow=electron.BrowserWindow;
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) { // eslint-disable-line global-require
app.quit();
}
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
const createWindow = () => {
console.log("Message");
// Create the browser window.
mainWindow = new BrowserWindow();
// and load the index.html of the app.
mainWindow.loadURL(`file://${__dirname}/ui/index.html`);
var env = process.env.NODE_ENV || 'production';
if(env==='dev'){
// Open the DevTools.
mainWindow.webContents.openDevTools();
}
// Emitted when the window is closed.
mainWindow.on('closed', () => {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null;
});
mainWindow.maximize();
const xmpp=require('./xmpp.js');
console.log(xmpp)
xmpp.xmppCli(mainWindow,ipcMain,dialog);
};
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow();
}
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.
并用这个文件处理它 xmpp.js
:
const {client, xml, jid} = require('@xmpp/client')
var clientInstance=null;
console.log('xmpp.js loaded')
const initXmpp= function(xmpp){
xmpp.on('error', err => {
console.error("Error occured",err.toString())
dialog.showErrorBox('Internal Error',err.toString())
})
xmpp.on('offline', () => {
console.log('', 'offline')
})
xmpp.on('online', async address => {
dialog.showMessageBox({'type':'info','message':"Online as:"+address.toString()})
})
xmpp.on('stanza', stanza => {
console.log('⮈', stanza.toString())
xmpp.stop()
})
process.on('unhandledRejection', function (reason, p) {
console.log('Possibly Unhandled Rejection at: Promise ', p, ' reason: ', reason)
})
xmpp.start()
}
module.exports.xmppCli=function(mainWindow,ipcMain,dialog){
ipcMain.on('login',(event,params)=>{
let jidVal=jid(params.username);
params.server="xmpp://"+params.server
console.log(jidVal.getLocal(),jidVal.getDomain(),params.server)
if(!clientInstance){
console.log("Client Works");
try{
clientInstance=new client({
'service':params.server,
'domain': jidVal.getDomain(),
'username':jidVal.getLocal(),
'password':params.password,
})
initXmpp(clientInstance)
} catch(e) {
console.error('Internal Error',e.message)
console.error(e.stack)
clientInstance=null;
}
}
});
}
另外我的ui由index.html
组成:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Login Page</title>
<link rel="stylesheet" href="../../node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="../../node_modules/roboto-fontface/css/roboto/roboto-fontface.css">
<style>
html, body, .container-fluid {
height: 100%;
font-family: 'Roboto', sans-serif;
}
#form_wrapper{
border:1px solid;
border-radius: 10px;
}
</style>
<script>window.$ = window.jQuery = require('../../node_modules/jquery/dist/jquery.min.js');</script>
<script src="../../node_modules/jquery/dist/jquery.min.js"></script>
<script src="./index_renderer.js"></script>
</head>
<body class="bg-secondary">
<div class="container-fluid d-flex justify-content-center align-items-center">
<div id="form_wrapper" class="p-2" style="background-color:white;">
<h1 class="text-center">XMPP KEY AGREEMENT CLI</h1>
<form id="loginForm">
<div class="form-group">
<label for="server">XMPP Server</label>
<input id="server" class="form-control" type="text" name="server" placeholder="eg. example.com" required>
</div>
<div class="form-group">
<label for="username">Username</label>
<input id="username" class="form-control" type="text" name="username" placeholder="eg. user@example.com" required>
</div>
<div class="form-group">
<label for="password">Password</label>
<input id="password" class="form-control" type="text" name="password" placeholder="Type your password here" required>
</div>
<button type="submit" class="btn btn-primary btn-lg btn-block">Login</button>
</form>
</div>
</div>
</body>
</html>
使用以下渲染器:
$(document).ready(function(){
const ipcRenderer = require('electron').ipcRenderer;
$("#loginForm").on('submit',function(e){
e.preventDefault();
console.log("Form Submitted");
//
let data=$(this).serializeArray().reduce(function(a, x) { a[x.name] = x.value; return a; }, {});
ipcRenderer.send('login',data)
})
})
但我的问题是,当我使用自签名证书启动我自己的本地 opefireserver 时。因此,我得到了一个神秘的错误,显示如下:
所以我的问题是:
- 如何调试这些类型的错误?我的意思是我找不到这个错误的位置。
- 我如何手动告诉 electron 或 xmpp.js 手动接受自签名证书>
我试图通过更改手动找出此错误的产生位置:
xmpp.on('error', err => {
console.error("Error occured",err.toString())
dialog.showErrorBox('Internal Error',err.toString())
})
进入这个:
xmpp.on('error', err => {
console.error("Error occured",err.toString())
})
仍然出现奇怪的错误。
当发生连接错误时,@xmpp/client
库似乎缺少 api 调用,如下例所示:
const {client, xml, jid} = require('@xmpp/client')
const initXmpp=function(xmpp){
xmpp.on('error', err => {
console.error("Error occured",err.toString())
// dialog.showErrorBox('Internal Error',err.toString())
})
xmpp.on('offline', () => {
console.log('', 'offline')
})
xmpp.on('online', async address => {
dialog.showMessageBox({'type':'info','message':"Online as:"+address.toString()})
})
xmpp.on('stanza', stanza => {
console.log('⮈', stanza.toString())
xmpp.stop()
})
process.on('unhandledRejection', function (reason, p) {
console.error('Possibly Unhandled Rejection at: Promise ', p, ' reason: ', reason)
})
try{
xmpp.start()
} catch(e) {
console.error(e.message)
}
}
try{
clientInstance=new client({
'service':"xmpp://0.0.0.0:5222",
'domain': "example.com",
'username':"admin",
'password':"admin",
});
initXmpp(clientInstance);
} catch(e) {
console.error(e);
}
我收到以下错误:
events.js:183
throw er; // Unhandled 'error' event
^
Error: self signed certificate
at TLSSocket.<anonymous> (_tls_wrap.js:1105:38)
at emitNone (events.js:106:13)
at TLSSocket.emit (events.js:208:7)
at TLSSocket._finishInit (_tls_wrap.js:639:8)
at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:469:38)
并且没有提供任何方式来处理它,那是因为 SSL/TLS 连接是由 nodejs 本身处理的,因此唯一的解决方案可以在这个 gthub answer.
上找到基于上面提到的解决方案实际上结合NODE_ENV
环境变量我将以下代码片段放在index.js
上:
if(env==='dev' || env=='debug'){
process.env.NODE_TLS_REJECT_UNAUTHORIZED=0;
}
另外,如果使用 this I would suggest to fork it and modify it to use latest version of ubuntu (or even a more stable docker image) and later version of openfire such as this 人的话。