我也在努力寻找解决方案。请注意,我将 Firebase 用于某些功能,但我会尽我所能记录逻辑。
到目前为止,我能够弄清楚的是:
- 将自定义标头附加到 HTTP 请求客户端
// landing.js - main page script snippet
function loadPage(path) {
// Get current user's ID Token
firebase.auth().currentUser.getIdToken()
.then(token => {
// Make a fetch request to 'path'
return fetch(`${window.location.origin}/${document.documentElement.lang}/${path}`, {
method: 'GET',
headers: {'X-Firebase-ID-Token': token} // Adds unverified token to a custom header
});
})
.then(response => {
// As noted below, this part I haven't solved yet.
// TODO: Open response as new webpage instead of displaying as data in existing one
return response.text();
})
.then(text => {
console.log(text);
})
.catch(error => {
console.log(error);
});
}
- 通过在服务器端检索相应的标头值来根据您的逻辑验证令牌
// app.js - main Express application server-side file
// First of all, I set up middleware on my application (and all other setup).
// getLocale - language negotiation.
// getContext - auth token verification if it is available and appends it to Request object for convenience
app.use('/:lang([a-z]{2})?', middleware.getLocale, middleware.getContext, routes);
// Receives all requests on optional 2 character route, runs middleware then passes to router "routes"
// middleware/index.js - list of all custom middleware functions (only getContext shown for clarity)
getContext: function(req, res, next) {
const idToken = req.header('X-Firebase-ID-Token'); // Retrieves token from header
if(!idToken) {
return next(); // Passes to next middleware if no token, terminates further execution
}
admin.auth().verifyIdToken(idToken, true) // If token provided, verify authenticity (Firebase is kind enough to do it for you)
.then(token => {
req.decoded_token = token; // Append token to Request object for convenience in further middleware
return next(); // Pass on further
})
.catch(error => {
console.log('Request not authorized', 401, error)
return next(); // Log error to server console, pass to next middleware (not interested in failing the request here as app can still work without token)
});
}
- 渲染并发回数据
// routes/index.js - main router for my application mounted on top of /:lang([a-z]{2})? - therefore routes are now relative to it
// here is the logic for displaying or not displaying the page to the user
router.get('/console', middleware.getTranslation('console'), (req, res) => {
if(req.decoded_token) { // if token was verified successfully and is appended to req
res.render('console', responseObject); // render the console.ejs with responseObject as the data source (assume for now that it contains desired DB data)
} else {
res.status(401).send('Not authorized'); // else send 401 to user
}
});
如您所见,我能够通过使用自定义中间件将代码模块化并使其简洁明了。它现在是一个有效的 API,使用身份验证和受限访问从服务器返回数据
我还没有解决的问题:
如上所述,该解决方案使用 fetch API,请求的结果是来自服务器 (html) 的数据,而不是新页面(即跟随锚链接时)。这意味着现在使用此代码的唯一方法是使用 DOM 操作并将响应设置为页面的 innerHTML。 MDN 建议您可以设置“位置”标头,该标头将在浏览器中显示一个新 URL(您希望指示的那个)。这意味着您实际上实现了您和我都想要的东西,但是如果您知道我的意思,我仍然无法理解如何以与浏览器相同的方式显示它,当您点击链接时。
无论如何,请让我知道您对此的看法以及您是否能够从我尚未解决的部分解决它