我有一些与数据库交互的 endpoints ( Cloud 功能) . 要访问这些 endpoints ,我需要使用电子邮件和密码[1]对用户进行身份验证,检索accessToken [2]并使用 Authorization: Bearer {accessToken}
标头对 endpoints 的每个请求进行授权 .
我使用php并努力思考如何在我的应用程序中管理经过身份验证的用户 .
TL; DR请在php中查看我的最终解决方案 . https://stackoverflow.com/a/52119600/814031
我在php会话中通过ajax传输accessToken,以便向 endpoints 签署cURL请求 . 显然没有其他方法可以使用firebase JS auth(据我所知[4]而言) .
My question is: 是否足以将 accessToken
保存在php会话中,并通过ajax POST请求将其与每个页面加载进行比较(参见下面的代码)?在php中处理这个问题会有什么更强大的策略?
Edit: A user pointed out使用经典的PHP会话与JWT令牌没有多大意义,我读了一下这个主题 . 关于Firebase - 这是需要考虑的事情吗? https://firebase.google.com/docs/auth/admin/manage-cookies
Firebase Auth为依赖会话cookie的传统网站提供服务器端会话cookie管理 . 与客户端短期ID令牌相比,此解决方案有几个优点,每次可能需要重定向机制才能在到期时更新会话cookie:
这是我得到的:
1. Login Page
如Firebase示例[3]中所述
function initApp() {
firebase.auth().onAuthStateChanged(function (user) {
if (user) {
// User is signed in.
// obtain token, getIdToken(false) = no forced refresh
firebase.auth().currentUser.getIdToken(false).then(function (idToken) {
// Send token to your backend via HTTPS
$.ajax({
type: 'POST',
url: '/auth/check',
data: {'token': idToken},
complete: function(data){
// data = {'target' => '/redirect/to/route'}
if(getProperty(data, 'responseJSON.target', false)){
window.location.replace(getProperty(data, 'responseJSON.target'));
}
}
});
// ...
}).catch(function (error) {
console.log(error);
});
} else {
// User Signed out
$.ajax({
type: 'POST',
url: '/auth/logout',
complete: function(data){
// data = {'target' => '/redirect/to/route'}
if(getProperty(data, 'responseJSON.target', false)){
// don't redirect to itself
// logout => /
if(window.location.pathname != getProperty(data, 'responseJSON.target', false)){
window.location.replace(getProperty(data, 'responseJSON.target'));
}
}
}
});
// User is signed out.
}
});
}
window.onload = function () {
initApp();
};
2. a php controller to handle the auth requests
public function auth($action)
{
switch($action) {
// auth/logout
case 'logout':
unset($_SESSION);
// some http status header and mime type header
echo json_encode(['target' => '/']); // / => index page
break;
case 'check':
// login.
if(! empty($_POST['token']) && empty($_SESSION['token'])){
// What if I send some bogus data here? The call to the Endpoint later would fail anyway
// But should it get so far?
$_SESSION['token'] = $_POST['token'];
// send a redirect target back to the JS
echo json_encode(['target' => '/dashboard']);
break;
}
if($_POST['token'] == $_SESSION['token']){
// do nothing;
break;
}
break;
}
}
3. the Main controller
// pseudo code
class App
{
public function __construct()
{
if($_SESSION['token']){
$client = new \GuzzleHttp\Client();
// $user now holds all custom access rights within the app.
$this->user = $client->request(
'GET',
'https://us-centralx-xyz.cloudfunctions.net/user_endpoint',
['headers' =>
[
'Authorization' => "Bearer {$_SESSION['token']}"
]
]
)->getBody()->getContents();
}else{
$this->user = null;
}
}
public function dashboard(){
if($this->user){
var_dump($this->user);
}else{
unset($_SESSION);
// redirect to '/'
}
}
}
注意:我知道这个sdk https://github.com/kreait/firebase-php并且我在那里的问题以及SO上的帖子中阅读了很多,但我感到困惑,因为有关于完全管理员权限等的讨论,我真的只与 endpoints 交互构建在firebase上(加上firebase auth和firestore) . 我还在使用php 5.6: - /
谢谢你的时间!
3 回答
我必须承认,firebase文档和示例以及不同服务的复杂性使我感到困惑,我认为,只有通过JavaScript才能对Web进行身份验证 . 那是错的 . 至少在我的情况下,我只需 login with email and password 到 retrieve a Json Web Token (JWT) ,即可签署所有对Firebase Cloud 功能的调用 . 而不是通过JavaScript处理奇怪的Ajax请求或设置令牌cookie,我只需要调用Firebase Auth REST API
以下是使用Fatfreeframework的最小案例:
Login form
Route
Controller
Class
Credits
在使用令牌时,你真的不应该在PHP中使用会话 . 标记应该在每个请求的头文件中发送(或cookie也可以) .
令牌的工作方式如下:1 . 您登录时,服务器会根据编码的某些信息创建一个令牌 . 您可以在每次请求时发回该令牌
基于令牌中编码的信息,服务器可以获得关于用户的信息 . 通常,某种用户ID在其中进行编码 . 服务器知道它是一个有效的令牌,因为它的编码方式 .
在您需要进行的每个请求上发送令牌,然后在PHP中,您可以将该令牌传递给其他API
听起来像@Chad K让你走上正轨( Cookies 和ajax - 冠军的早餐...... :),虽然我想从我的工作系统中分享我的代码(当然还有一些'隐私'的东西!)
查找/ ****类型注释,了解您需要自己设置的内容(您可能希望以不同的方式执行其他一些firebase事务 - 请参阅文档...)
LOGIN.php页面(我发现整体更简单,以保持这一点 - 请参阅说明以了解原因....)
现在,在您希望用户看到的每个页面上(在我的情况下,它都通过index.php#something - 这使得它更容易.... :)
希望这可以帮助 . 它来自我的工作系统,其中包括我沿途放置的一些额外功能,但主要是直接来自firebase,所以你应该能够很好地跟进 .
看起来比原来的路线要简单得多 .