【问题标题】:Angularjs oauth popup window, wait for JSON responseAngularjs oauth 弹窗,等待 JSON 响应
【发布时间】:2015-11-10 13:25:27
【问题描述】:

我需要提出一个 oauth 请求,并且我想在新窗口中启动该请求。

我知道我可以这样打开窗口:

var authWindow = $window.open("/auth/google/signin", "");

我的服务器将处理回调并以 JSON 响应:

 app.get('/auth/google/signin',
    passport.authenticate('google', { scope: 'https://www.googleapis.com/auth/plus.login'}),
    function(req, res, next) {
      // The request will be redirected to Google for authentication, so this
      // function will not be called.
    }
  );

app.get('/auth/google/callback',
    function(req, res, next) {
      passport.authenticate('google', function(err, user, info) {
        console.log('google authenticate callback');

        // do some stuff, then send back token and user...

        res.json({
          token:token,
          user: user
        });

      })(req, res, next);
    }
  );

我需要等到弹出窗口重定向到 /auth/google/callback 并且从服务器返回 JSON 数据。

如何等待来自服务器的重定向和 JSON 响应?

等到我得到 JSON 数据后,最好的方式是什么?打回来? postMessage()?

【问题讨论】:

  • 您不能打开“隐藏窗口”,而是创建一个隐藏的 iframe 并将结果存储在 cookie 中。
  • 抱歉不需要隐藏窗口,因为用户需要输入凭据。但是,一旦誓言完成而不使用 cookie,我是否应该能够从子窗口取回 JSON 数据?
  • 不,您需要使用cookies传输数据。大多数开发人员创建一组 3 个或更多 MD5 散列字符串以匹配数据库中的字段。使用 cookie 传输 3 个哈希值。您可以通过将 SSL 添加到您用于 oAuth 的页面来更进一步。

标签: javascript json angularjs oauth-2.0 passport.js


【解决方案1】:

当然可以。
这是我的解决方案:使用 JS 和 Nodejs 作为后端。
主要技巧是:window.postMessage
主要流程是:
1. 客户端询问注册页面,服务器响应。
2. 注册页面触发oauth进程,会使用"window.open("http://your_server/oauth_page")"
3. oauth_page 做了几件事

一种。检查状态(默认/成功) 湾。如果处于默认状态,则使用 window.opener.postMessages('ready','*') 告诉主窗口(注册页面)我准备好了。 然后注册页面会监听消息并返回分配的 oauth url。 因为我在一页中有几个 oauth 方法(Github/Google+/Facebook) C。 oauth_page 会将 XHR 请求发送到服务器。 d。服务器会将redirect_url 发送回oauth_page。 e. oauth_page 将使用“window.location_url”进行重定向。现在您可以看到授权页面。 f.授权结果将发送回服务器。 g.server 将运行交换代码,获取 access_token 并获取您想要的信息......我想你知道这个过程。(护照库做。) h.将 oauth_page 返回到同一个子窗口!神奇的是 window.opener 仍然是注册页面,所以你可以像以前一样发回结果。

4.注册页面会收到结果!。


这个过程看起来很长,但代码很简单。 这是我的注册页面代码

doctype html
html
    head
        title= title
    body
        h1= title
        p Welcome to #{title}
        button(id="github-oauth" data-oauth-server-url="github") Sign up by Github
        button(id="google-oauth" data-oauth-server-url="google") Sign up by Google
        button(id="facebook-oauth" data-oauth-server-url="facebook") Sign up by Facebook
        script(type="text/javascript").
            window.onload = function() {
                var oauth_page;
                var oauth_server_url;
                function createOauthButtonListner(elem) {
                    elem.addEventListener("click", function () {
                        oauth_page = window.open("http://localhost:3000/oauth_page");
                        //determine which button is triggered.
                        oauth_server_url = elem.getAttribute("data-oauth-server-url");
                        console.log(oauth_server_url);
                    })
                };
                window.addEventListener('message', function (e) {
                    if (e.data == "ready") {
                        // send oauth url
                        oauth_page.postMessage(oauth_server_url, "http://localhost:3000");
                    } else {
                        // return oauth resut
                        console.log(e.data);
                    }
                }, false);
                createOauthButtonListner(document.getElementById("github-oauth"));
                createOauthButtonListner(document.getElementById("google-oauth"));
                createOauthButtonListner(document.getElementById("facebook-oauth"));
            }

这是我的 Oauth_page

doctype html
html
    head
        title= "Oauth Page"
    body
        p Welcome to Oauth page
        p#status #{status}
        p#content #{content}
        script(type="text/javascript").
            window.onload = function(){
                // return msg to host window
                if (document.getElementById('status').innerHTML == 'success') {
                    window.opener.postMessage(document.getElementById('content').innerHTML, '*');
                    window.close();
                }else if(document.getElementById('status').innerHTML == 'default'){
                    window.opener.postMessage('ready', '*');
                }
                // redirect to oauth page
                window.addEventListener('message', function (e) {
                    console.log(window);
                    if (e.origin != "http://localhost:3000") {
                        console.log("error");
                        return;
                    } else {
                        if (document.getElementById('status').innerHTML == 'default') {
                            var xhttp = new XMLHttpRequest();
                            xhttp.open("GET", e.data, true);
                            xhttp.send();
                            xhttp.onreadystatechange = function () {
                                if (xhttp.readyState == 4 && xhttp.status == 200) {
                                    window.location.href = JSON.parse(xhttp.responseText).redirect_url;
                                }
                            };
                        }
                    }
                }, false);
            };

我的服务器端代码(相当混乱:P)

router.get('/oauth_page', function (req, res, next) {
    res.render('oauth', {status: 'default', content: 'none'});
})

// for github oauth
router.get('/github', function(req, res){
  var github_oauth_url = "https://github.com/login/oauth/authorize" +
      "?client_id=" + github_client_id  +
      "&scope=user" ;
  res.send(JSON.stringify({"redirect_url":github_oauth_url}));
});

router.get('/github/callback', function(req, res){
    var code = req.query.code;
    var token_option = {
        url:"https://github.com/login/oauth/access_token",
        method:"POST",
        form:{
            code: code,
            client_id: github_client_id,
            client_secret: github_secret_id
        }
    };
  request(token_option, function(err, response, body){
      if(err){
          res.send(response);
      }
      var regex = /\=([a-zA-Z0-9]+)\&([a-zA-Z])+\=([a-zA-Z0-9]+)/;
      var result = body.match(regex);
      console.log(result, body);
      var token = result[1];

      var info_option = {
          url:"https://api.github.com/user",
          method:"GET",
          headers:{
              "User-Agent": "Awesome-Octocat-App",
              "Authorization":"token "+ token
          }
      }
      request(info_option, function(err, response, body){
         if(err){
             res.send(err);
         }
          res.render('oauth', {status: 'success', content:body});
      });
  });
});

在注册页面,打开控制台就可以看到结果了。
随时问我问题;)
我在一周内为此工作。
希望它可以帮助你。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-10
    • 1970-01-01
    相关资源
    最近更新 更多