如何检测初始页面加载是不是来自重定向

Posted

技术标签:

【中文标题】如何检测初始页面加载是不是来自重定向【英文标题】:How to detect if initial page load was from a redirect如何检测初始页面加载是否来自重定向 【发布时间】:2018-05-16 04:55:11 【问题描述】:

我有一个 reactjs 应用程序,它使用 firebase 对用户进行身份验证,并通过使用 firebase xxxWithRedirect() 方法链接到各种身份验证提供程序帐户。例如,从 /users/settings 页面调用以下内容。

var user = this.props.fb.auth().currentUser;
if (user !== null) 
  var provider = new firebase.auth.GoogleAuthProvider();
  user.linkWithRedirect(provider).then(function () 
      console.log('Successfully linked with Google account');
    ,
    function (error) 
      console.log('Failed to link with Google account:  code=' + error.code + ' message=' + error.message);
    );

else 
  console.log('user is null');

身份验证完成后,身份验证提供程序会重定向回发起重定向的应用页面。例如:

导航到http://localhost:3000/users/settings

在应用程序路由处理中,我希望能够确定初始页面加载是否来自重定向。这样我就可以确定在从身份验证提供程序重定向的情况下是否应该将用户带回 /users/settings 页面,或者如果用户尚未经过身份验证并且不是身份验证重定向页面加载,则应该返回 / 页面.

        <Switch>
          <Route exact path="/" component=Home/>
          <Route exact path="/users/profile" render=() => (isLoggedIn() ? <UserProfile fb=fb/> : <Redirect to="/"/>)/>
          <Route exact path="/users/settings" render=() => (isLoggedIn() ? <UserSettings fb=fb/> : <Redirect to="/"/>)/>
          <Route component=NoMatch/>
        </Switch>

有没有办法判断 reactjs 匹配的路由路径是否来自重定向?

【问题讨论】:

你不能告诉 firebase auth 重定向到特定页面吗? @AndréWerlang - Firebase 身份验证实际上正在做我想做的事,它尝试重定向回 /users/settings 页面,这是身份验证请求的来源。不幸的是,到此路径的导航发生在用户身份验证完成之前,即尚未设置 firebase 用户,因为这在 firebase.auth().onAuthStateChanged() 中异步发生。我不想导航到这个 /users/settings 页面,除非有 firebase 用户登录。所以这真的是一个时间问题。我想在用户登录后将它们带到 /users/settings。 【参考方案1】:

要么:1)找到一种方法来为重定向的东西(如果可能)提供自定义 URL,并在其上放置类似“?redirect=true”的内容,否则 2) 使用服务器会话变量来保存一个标志,表明它将期望获得重定向。

【讨论】:

这些都是好主意。我不确定我是否可以通过 firebase 登录并链接到重定向方法,例如我在这里使用的方法 - auth.currentUser.linkWithRedirect(provider); 使用 Fiddler 或其他工具检查重定向时传入的 HTTP 标头。也许已经有一些你可以检测到的标题属性/属性。我之前没有想到。实际上,您还可以使用 Web 过滤器(servlet/java)来记录标头属性的内容,这是另一种检查(监控 http)以查看您拥有的内容的方法 @ClayFerguson 如何检查浏览器发起的重定向中的请求标头? @AndréWerlang google this: "java servlet filter to print header values" ***.com/questions/25247218/… @ClayFerguson 好吧,你说的是服务器端解决方案【参考方案2】:

如果存在时间问题,Firebase Auth 在填充 user 对象之前返回您的页面,则需要有一种方法在准备好时等待/检索此信息。

来自https://firebase.google.com/docs/auth/web/google-signin#redirect-mode:

firebase.auth().getRedirectResult().then(function(result) 
  if (result.credential) 
    // This gives you a Google Access Token. You can use it to access the Google API.
    var token = result.credential.accessToken;
    // ...
  
  // The signed-in user info.
  var user = result.user;
).catch(function(error) 
  // Handle Errors here.
  var errorCode = error.code;
  var errorMessage = error.message;
  // The email of the user's account used.
  var email = error.email;
  // The firebase.auth.AuthCredential type that was used.
  var credential = error.credential;
  // ...
);

来自https://firebase.google.com/docs/reference/js/firebase.auth.Auth#getRedirectResult:

如果登录成功,返回登录用户。如果登录是 不成功,因错误而失败。如果没有重定向操作 调用时,返回一个带有空用户的 UserCredential。

所以此时您将知道用户何时通过身份验证并进行处理。

【讨论】:

Werlang - 正如您所描述的那样,我正在处理重定向结果。问题是在浏览器已经被重定向并且reactjs路由器拦截它并尝试处理它之后调用这个异步函数。这都是在填充 firebase 用户对象之前完成的。这是来自控制台的序列。导航到localhost:3000/users/settings App.js:37 未登录referrer = 成功重定向App.js:276 重定向操作类型= 链接重定向url = / App.js:338 用户登录:Dallas Clement uid=hjCA3w7DHAVkuuzp6S5tv1HQJT53 无法响应路由器等到firebase.auth().getRedirectResult() 解决? Werlang - 我希望它可以。那将解决一切。这些事情正在不同的线程中完成。但是,如果我能以某种方式确定导航来自重定向,我可能会记住这一点,并且在 firebase 用户登录后,将用户导航到该页面。 @user2800837 我会说您的初步询问无法以积极的方式完成。你需要用router/Home组件来处理它。【参考方案3】:

@AndreWerlang 我能够通过使用firebase.auth().getRedirectResult() 方法中提供的 operationType 来解决我的问题。在这种特殊情况下,我想将用户带回 /user/settings 页面,因为用户可以在此处链接其他身份验证提供程序帐户。通过检查 operationType 是否试图“链接”另一个帐户,我只需再次重定向到 /user/settings 页面,因为当从身份验证提供程序接收到第一次重定向到 /users/settings 时,firebase 用户并不完整。这是代码。

componentDidMount = () => 
    firebase.auth().getRedirectResult().then(function(userCredential) 
        console.log('Successfully redirected');
        var operationType = userCredential.operationType;
        if (operationType) 
            console.log('Redirect operationType = ' + operationType);
            switch (operationType) 
                case 'signIn':
                   break;
                case 'link':
                   this.setState(redirectToUserSettings: true);
                   break;
                case 'reauthenticate':
                   break;
                default:
            
        
    .bind(this), function(error) 


render() 
    return (
        <div className="App">
            <Router history=history>
                <div>
                    this.state.redirectToUserSettings && <Redirect to="/users/settings" />
                </div>
             </Router>
        </div>
    );

【讨论】:

以上是关于如何检测初始页面加载是不是来自重定向的主要内容,如果未能解决你的问题,请参考以下文章

检测页面来自后退按钮的方法

检测浏览器是不是正在执行重定向

AngularJS - 如何在整个页面加载时进行重定向?

PHP 标头重定向不会在 IE 中重新加载 <iframe>

如何根据用户的状态位置将用户重定向到不同的 index.php 页面

如何使用 JQuery 重定向,加载另一个页面但在请求中发送了一些 POST 参数?