【问题标题】:How to redirect the browser from server side after firebase authenticates userfirebase对用户进行身份验证后如何从服务器端重定向浏览器
【发布时间】:2018-05-31 21:30:52
【问题描述】:

我在 firebase 上托管了一个 node.jsexpress.js 应用程序。它托管在:https://spice-ai.firebaseapp.com/

我想在用户认证后重定向到不同的页面。但是,res.redirect('/user') 仅重定向到 app.get,而不是 app.post。这很奇怪,谁能告诉我为什么?

我的index.ts

import * as express   from 'express'           ;
import * as admin     from 'firebase-admin'    ;
import * as functions from 'firebase-functions';
import * as path      from "path"              ;
import * as math      from 'mathjs'            ;


import { Option, some, none } from 'fp-ts/lib/Option';

import * as bodyParser            from "body-parser";
import { body, validationResult } from 'express-validator/check';
import { sanitizeBody }           from 'express-validator/filter';


const accountKeyPath = path.join(__dirname, '../credentials/serviceAccountKey.json');
const accountKey     = require(accountKeyPath);

const adminSDKPath   = path.join(__dirname, '../credentials/spice-ai-firebase-adminsdk.json');
const adminSDK       = require(adminSDKPath);

const firebaseAdmin = admin.initializeApp({
      credential : admin.credential.cert(adminSDK)
    , databaseURL: accountKey['databaseURL']
});

const dbRef = new Proposal(firebaseAdmin, 'datasets');
const auth  = firebaseAdmin.auth()


// create HTTP server
const app = express();


// use json form parser middleware
app.use(bodyParser.json());

// use query string parser middlware
app.use(bodyParser.urlencoded({ extended: true }));

// set view engine
app.set('views', path.join(__dirname, '../src/view'))
app.set('view engine', 'pug');

// set static file source
app.use(express.static(path.join(__dirname, "../public")));

app.use(cors({origin: 'http://localhost:5000'}));
app.use(cors({origin: '/'}    ));
app.use(cors({origin: '/user'}));



app.get('/', (req,res) => {

    res.render('pages/login', {})
    // a res.redirect('/user') redirects immediately here

});


app.post('/', (req, res) => {

    // this does not redirect
    console.log('\n+++++++++++++++++++++++++++ POST')
    res.redirect('/user');

})

app.get('/user' , (req, res) => {

    console.log('\n############################### GET /user')
    res.render('pages/user')
});

exports.app = functions.https.onRequest(app);

前端对应的app.js就是post一个json

const config = {
    "apiKey"           : ""
    "authDomain"       : ""
    "databaseURL"      : ""
    "projectId"        : ""
    "storageBucket"    : ""
    "messagingSenderId": ""
};


firebase.initializeApp(config);
const auth = firebase.auth(); 

auth.onAuthStateChanged(user => {

    if (user) {

        console.log("loaded page with user: ", user['email'])
        user.getIdToken(true)

        .then( idToken => {

            console.log('user token: ', idToken)
            post_utoken(idToken);

        })

    } else {

        console.log('no user found')

    }
});


/**
    @Use: send user id to server
*/
function post_utoken(tok){

    var data = {};
    data.userToken = tok

    $.ajax({
          type        : 'POST'
        , url         : 'http://localhost:5000/'
        , data        : data
        , dataType    : 'json'

        , success : function(data) {

            console.log('\n======================================')
            console.log('success sending data from app.js')

        }
    })
}

一切都很标准。此外,在我的bash 上,我可以看到重定向和app.get('/user' ..) 都已触发,因为我有:

++++++++++++++++++++++++++ POST
info: Execution took 1 ms, user function completed successfully
127.0.0.1 - - [31/May/2018:22:03:28 +0000] "POST / HTTP/1.1" 302 27 "http://localhost:5000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36"
[hosting] Rewriting /user to local function app
info: User function triggered, starting execution
info: 
############################### GET /user
info: Execution took 78 ms, user function completed successfully
127.0.0.1 - - [31/May/2018:22:03:28 +0000] "GET /user HTTP/1.1" 200 6547 "http://localhost:5000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36"

但是在客户端我仍然在localhost:5000,即使app.get('/user'...) 已经被解雇了。

================================================ ================

编辑:

我发现对于ajax 在发布到服务器时所做的事情存在概念上的误解。我想将所有应用程序状态集中在服务器端,所以如果可能的话,我想在app.get('/' ..) 回调中将redirect/user。所以这意味着客户端没有ajax,如果是这样,我将如何将信息发送到服务器端?我可以用socket.io 做到这一点还是过度设计它?如果是这样,我会怎么做?

再次,我必须从服务器端重定向,因为我使用 index.ts 作为我的应用程序控制器,所以我根本不希望在客户端进行状态更改逻辑,除了由于 firebase 约束而进行的用户身份验证。

【问题讨论】:

  • 我的意思是...您是否期​​望服务器端重定向在执行 ajax 请求后重定向页面?或者是什么。因为,它不会。
  • @KevinB 是如果我将代码 sn-p res.redirect('/user') 放在对app.get('/' (req, res) => ...) 的响应中,那么它会按预期重定向。 app.post 之后我应该如何重定向?
  • 使用 javascript。 get 请求重定向,因为您在没有 ajax 的情况下完成了它。重定向的 ajax 请求不会重定向浏览器。

标签: javascript node.js firebase express firebase-authentication


【解决方案1】:

您的期望略有偏差。

当服务器以HTTP Status Code 302 响应时,它会告诉浏览器下一步要去哪里,这在使用GET 请求导航时很有意义,但在通过 ajax 发布数据时就没有那么多了,您可以完全控制什么接下来发生。

其实比较简单,试试这样的:

success : function(data) {
    window.location.href = '/user'
}

这正是您所期望的,在客户端完成。

如果您确实需要在服务器端完成,则添加一个 html 表单并通过 javascript 提交,这样浏览器将处理请求并采取适当的操作。

将此添加到您的 HTML:

<form id="userform" action="/" method="POST" style="display: none">
    <input id="userform_email" name="email" value="">
</form>

然后在你的脚本中:

auth.onAuthStateChanged(user => {
    if (user) {
        document.getElementById('userform_email').value = user['email'];
        document.getElementById('userform').submit();
    } else {
        console.log('no user found')
    }
});

您正在做的是创建一个不可见的表单,一旦 Firebase 完成它的工作,该表单就会被提交。数据将以不同的形式到达服务器,因此您可能需要在那里进行一些调整。

【讨论】:

  • 所以 Ajax 调用暂时将控制权交给了服务器?并在完成计算之前等待响应?有没有办法在没有 Ajax 的情况下发布到服务器,所以我可以在服务器端重定向?这样我就没有应用程序状态逻辑分散在代码库中
  • Gomez 你的意思是 html 格式吗?不幸的是,我在这里工作在 firebase 的限制范围内,据我所知,没有办法从服务器端监听身份验证状态更改,只能从​​客户端监听。所以我必须在客户端监听并在auth.onAuthStateChanged 回调中插入对服务器的调用...
猜你喜欢
  • 2016-10-12
  • 2020-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-25
  • 1970-01-01
  • 2020-05-18
  • 1970-01-01
相关资源
最近更新 更多