我正在尝试在Chrome扩展程序中设置身份验证。我只是希望用户能够单击扩展图标,使用电子邮件+密码登录,然后才能使用扩展的不同组件。如果扩展弹出窗口已关闭,则不必再次登录。
我一直严格遵循文档here,here和the Chrome Extension specific documentation here,我的开发经验非常有限。
这是我的manifest.json
。
{
"name": "Extension",
"version": "0.1",
"description": "",
"permissions": [
"tabs",
"activeTab",
"storage"
],
"content_security_policy": "script-src 'self' https://www.gstatic.com/ https://*.firebaseio.com https://*.firebase.com https://www.googleapis.com; object-src 'self'",
"background": {
"page":"background.html",
"persistent": true
},
"browser_action": {
"default_popup": "popup.html",
"default_icon": {}
},
"manifest_version": 2
}
我的background.html
和background.js
与我上面链接的最后一个例子严格相同,除了当然我用自己的替换了Firebase配置。
我的popup.html
是:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<script src="https://www.gstatic.com/firebasejs/5.10.0/firebase.js"></script>
<script src="firebase/initialize.js" charset="utf-8"></script>
<script src="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.js"></script>
<link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.css"/>
<link type="text/css" rel="stylesheet" href="styles/popup.css" />
</head>
<body>
<h1>Extension</h1>
<div id="firebaseui-auth-container"></div>
<!-- Firebase App (the core Firebase SDK) is always required and must be listed first -->
<script src="src/popup.js"></script>
</body>
</html>
其中initialize.js
只是Firebase初始化脚本而我的popup.js
是:
//Initizalier FirebaseUI instance
var ui = new firebaseui.auth.AuthUI(firebase.auth());
//Define sign-in methods
var uiConfig = {
callbacks: {
//Callbacl if sign up successful
signInSuccessWithAuthResult: function(authResult) {
// User successfully signed in.
// Return type determines whether we continue the redirect automatically
// or whether we leave that to developer to handle.
//Script to replace popup content with my Extension UI
return false;
},
},
signInOptions: [
{
provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
requireDisplayName: false
}
],
};
//Initialize UI
ui.start('#firebaseui-auth-container', uiConfig);
使用这个,我可以说每次点击扩展图标时登录都有效,但如果我关闭并重新打开弹出窗口,我必须再次登录。我几乎每个地方都在询问这个问题。我也尝试将this stackoverflow question的答案问到我的background.js
剧本,但无济于事。
如果我没有完全迷失,我想我已经知道为什么会这样。如果我没有弄错,浏览器操作弹出窗口会覆盖后台页面/脚本正在执行的操作。但是我不确定我应该修改什么。我也看过this about authenticating Firebase with Chrome Extensions,但我无法理解它是如何融入我的工作中的。
此时我不知道接下来该做什么。
我找到了解决问题的方法。 @cloop在我所链接的问题中给出的答案是正确的,但为了后来会遇到这个问题的人,我会以自己的方式解释。我希望它会更适合初学者,因为我自己不是开发人员。
请注意,这仅仅是我获得MVP的解决方案,很可能有更好的方法来解决这个问题。
首先,请勿使用Firebase UI库,因为这与Chrome扩展程序不兼容。我将假设你已经完成了Chrome Extension tutorial以及Firebase Authentication文档的基础知识。
现在我们必须放弃我们迄今为止所拥有的所有东西并重新开始一个空的扩展。我们将为它设置电子邮件+密码验证。
首先我们创建清单:
{
"name": "Test extension",
"version": "0.1",
"description": "An extension to test Firebase auth",
"permissions": [/*Insert necessary permissions*/],
"content_security_policy": "script-src 'self' https://www.gstatic.com/ https://*.firebaseio.com https://*.firebase.com https://www.googleapis.com; object-src 'self'",
"background": {
"page":"background.html",
"persistent": true
},
"browser_action": {
"default_popup": "popup.html",
},
"manifest_version": 2
}
background.html
是链接到background.js
脚本的背景页面。这是因为我们必须在页面的<head>
中加载firebase,然后才能在脚本中初始化它,例如参见脚本here。 popup.html
将是我们将根据身份验证状态动态加载的页面。它链接到脚本popup.js
并且只包含div元素#container
。我们将立即向该弹出窗口添加一个事件监听器,以使用Messaging API将消息发送到后台脚本。
window.addEventListener('DOMContentLoaded', (_event) => {
console.log("DOM loaded and parsed");
//Send a message to background script informing that the page is loaded
chrome.runtime.sendMessage({type: "popupLoad"}, function (response) {
if (response.type == "loggedIn") {
let htmlString = /*Your extension UI's HTML*/;
document.querySelector("#container").innerHTML(htmlString);
} else if (response.type == "loggedOut") {
let htmlString = /*Log in form HTML*/
document.querySelector("#container").innerHTML(htmlString);
};
});
所以我们在这里完成的是在我们的popup.html
的DOM完全加载以查询身份验证状态时向后台脚本发送消息。后台脚本将向我们发送一个response
或loggedIn
类型的loggedOut
对象,允许我们决定我们应该为弹出窗口加载什么接口。
现在我们来看看后台脚本。
首先,您应该初始化Firebase。
var config = {
/*Your config parameters from the Firebase console*/
};
firebase.initializeApp(config);
现在我们需要添加一个消息监听器。请注意,这将收听来自任何Chrome环境(标签,窗口,弹出脚本等)的任何消息,因此我们必须确保我们采取正确的消息类型。这就是我在弹出脚本消息创建中使用{type: "popupLoad"}
的原因。我的所有消息都至少有一个type
属性。
chrome.runtime.onMessage.addListener(
function(message, _sender, _sendResponse) {
if (message.type == "popupLoad") {
//Get current authentication state and tell popup
let user = firebase.auth().currentUser;
if (user) {
sendResponse({type: "loggedIn"});
} else {
sendResponse({type: "loggedOut"});
};
} else if (message.type == "other") {
//handle other types of messages
};
});
到目前为止我们所做的是,只要用户点击扩展图标,我们就能够根据身份验证状态决定弹出窗口的界面。当然,如果用户退出,他们将看到我们的登录/注册表单。此表单的按钮应该有一个事件监听器,它将一条消息(例如loginAttempt
类型)发送到后台脚本,然后后台脚本应该响应弹出脚本,如果登录成功则允许我们替换#container
内容与我们的扩展的UI。在这里,我们看到扩展实际上是单页面应用程序。
我必须在后台脚本中使用方法firebase.auth().onAuthStateChanged()
,如果我没有弄错的话,如果检测到auth状态的变化,那么它基本上就是一个事件监听器。
我不会详细介绍其他细节,但我希望这对于像我这样的初学者来说已经足够了,并且能够提出一个可行的原型。
简而言之:
如果有人注意到这个答案的任何问题,请不要犹豫。一些信誉归功于无数人,他们非常友好地帮助我开发Discord或者我发送电子邮件的少数开发人员并让我走上正轨。