我受命为基于Firebase的Android应用程序构建Web界面。我有一些与数据库交互的端点(云函数)。要访问这些端点,我需要使用电子邮件和密码[1]对用户进行身份验证,检索accessToken [2]并授权使用Authorization: Bearer {accessToken}标头对端点的每个请求进行授权。
Authorization: Bearer {accessToken}
我使用php并竭尽全力想如何在我的应用程序中管理经过身份验证的用户。
我通过php会话中的ajax传输accessToken,以将cURL请求签名到端点。显然,除了使用firebase JS auth之外,别无其他方法(据我所知[4])。
我的问题是: 是否足以将其保存accessToken在php会话中,并通过ajax POST请求将其与每个页面加载进行比较(请参见下面的代码)?在php中,有什么更健壮的策略来解决这个问题?
accessToken
编辑:一位用户指出,使用带有JWT令牌的经典php会话没有多大意义,我读了有关该主题的文章。那么关于Firebase- 这是要考虑的事情吗? https://firebase.google.com/docs/auth/admin/manage- cookies
Firebase Auth为依赖会话cookie的传统网站提供服务器端会话cookie管理。与客户端短暂的ID令牌相比,此解决方案具有多个优点,客户端短暂的ID令牌可能每次需要使用重定向机制来在到期时更新会话cookie:
这是我得到的:
1.登录页面
如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.一个PHP控制器来处理身份验证请求
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.主控制器
// 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上的文章里也读到很多,但是我很困惑,因为这里有关于完全管理员的讨论。权限等。我实际上仅与基于Firebase的端点进行交互(加上firebase auth和firestore)。而且我仍然在php 5.6上:-/
谢谢你的时间!
我不得不承认,firebase文档和示例的复杂性以及不同的服务使我非常困惑,以至于我认为只能通过JavaScript进行Web身份验证。错了 至少对于我来说,我只是 使用电子邮件和密码登录 以 检索Json Web令牌(JWT) ,以对Firebase云功能的所有调用进行签名。无需处理奇怪的Ajax请求或通过JavaScript设置令牌cookie,我只需要调用FirebaseAuth REST API
这是使用Fatfreeframework的最小情况:
登录表单
<form action="/auth" method="post"> <input name="email"> <input name="password"> <input type="submit"> </form>
路线
$f3->route('POST /auth', 'App->auth');
控制者
class App { function auth() { $email = $this->f3->get('POST.email'); $password = $this->f3->get('POST.password'); $apiKey = 'API_KEY'; // see https://firebase.google.com/docs/web/setup $auth = new Auth($apiKey); $result = $auth->login($email,$password); if($result['success']){ $this->f3->set('COOKIE.token',$result['idToken']); $this->f3->reroute('/dashboard'); }else{ $this->f3->clear('COOKIE.token'); $this->f3->reroute('/'); } } }
类
<?php use GuzzleHttp\Client; class Auth { protected $apiKey; public function __construct($apiKey){ $this->apiKey = $apiKey; } public function login($email,$password) { $client = new Client(); // Create a POST request using google api $key = $this->apiKey; $responsee = $client->request( 'POST', 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=' . $key, [ 'headers' => [ 'content-type' => 'application/json', 'Accept' => 'application/json' ], 'body' => json_encode([ 'email' => $email, 'password' => $password, 'returnSecureToken' => true ]), 'exceptions' => false ] ); $body = $responsee->getBody(); $js = json_decode($body); if (isset($js->error)) { return [ 'success' => false, 'message' => $js->error->message ]; } else { return [ 'success' => true, 'localId' => $js->localId, 'idToken' => $js->idToken, 'email' => $js->email, 'refreshToken' => $js->refreshToken, 'expiresIn' => $js->expiresIn, ]; } } }
学分