【问题标题】:Steam authentication with Angular使用 Angular 进行 Steam 身份验证
【发布时间】:2017-12-25 19:31:31
【问题描述】:

我正在尝试从 Angular 的主页使用 Steam 进行身份验证,但每当我点击按钮(在 AppComponent 中有指向 login() 函数的 (click) 事件),而不是被重定向到 Steam 页面,当前页面被刷新,没有任何反应。

这是服务器端代码:

'use strict';

const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io').listen(server);
const jwt = require('express-jwt');
const cors = require('cors');
const passport = require('passport');
const SteamStrategy = require('passport-steam').Strategy;
const mongoose = require('mongoose');

app.use(cors());
mongoose.connect('mongodb://localhost:27017/database_test');

passport.serializeUser((user, done) => {
    done(null, user);
});

passport.deserializeUser((obj, done) => {
    done(null, obj);
});

passport.use(new SteamStrategy({
        returnURL: 'http://localhost:3000/auth/steam/return',
        realm: 'http://localhost:3000',
        apiKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
    }, 
    (identifier, profile, done) => {
        process.nextTick(() => {
            profile.identifier = identifier;
            return done(null, profile);
        });
    }
));

app.use(passport.initialize());
app.use(passport.session());

app.get('/auth/steam',
    passport.authenticate('steam', { failureRedirect: 'http://localhost:4200/home' }),
    (req, res) => {
        res.json({"success": true, "res": res});
    }
);

app.get('/auth/steam/return', 
    passport.authenticate('steam', { failureRedirect: 'http://localhost:4200/home' }),
    (req, res) => {
        res.json({"success": true, "res": res});
    }
);

server.listen(3000, () => {
    console.log('Backend listening on port 3000.');
});

这是AuthenticationService

import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs';
import { JwtHelper, tokenNotExpired } from 'angular2-jwt';
import 'rxjs/add/operator/map';

@Injectable()
export class AuthenticationService {

  domain = 'http://localhost:3000';

  constructor(private http: Http) { }

  login() {
    return this.http.get(this.domain + '/auth/steam').map(res => res.json());
  }

}

这是AppComponent

import { Component } from '@angular/core';
import { AuthenticationService } from './authentication.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [ AuthenticationService ]
})
export class AppComponent {

  constructor(private authService: AuthenticationService) { }

  login(): void {
    this.authService.login().subscribe(data => {
      alert(data);
    });
  }

}

两台服务器都在运行(Angular 和 Node)。

编辑:我添加了按钮而不是链接,日志显示Same-origin policy 存在错误。

【问题讨论】:

  • 只是想补充一下,感谢您使用 Steam 做事。我大部分时间都在用 Angular 处理商业/公司的东西,从 StackOverflow 流量来看,大多数其他人都是。你在做一些我认为与游戏相关的事情上很独特!祝你好运,先生,玩得开心,然后为我们其他人玩得更开心:)

标签: angular authentication passport.js steam-web-api


【解决方案1】:

简单地说,你不能将你的 Angular 服务重定向到你的后端=>steam=>后端回调 url。您必须将用户重定向到那里。

所以不要调用authService.login(),只需添加一个直接链接,就像其他地方说的那样。我没有在您的后端代码中看到第一个链接,但前端代码建议 /auth/steam 就像在 SteamStrategy 文档中一样。

所以,第一步是这样的:

// change the login() method on AuthService
login() {
  window.location.href = "http://localhost:3000/auth/steam";
}

(您需要从 environment 或稍后获取该 URL。)

现在发生了什么:

  1. 浏览器转到localhost:3000/auth/steam
  2. Node 将浏览器重定向到 steam openId
  3. Steam,在成功登录和授权后,重定向回http://localhost:3000/auth/steam/return

接下来会发生什么?

  • 首先,将 Passport 策略中的配置文件数据保存到用户的配置文件中,或者至少保存到用户的会话中。
  • 然后,将用户重定向回 Angular 应用程序。像这样的:

    res.redirect('/public/#/authcallback)`

(在此处使用 HashLocationStrategy 以便您清楚地看到我将您重定向到哪里。)

  • 现在,您在 Angular 中的 /authcallback 路由可能应该再次直接到达端点,以获取身份验证数据,然后再进行自己的重定向。

替代方案:

现在,最后一部分可以用不同的方式完成。你可以做一些事情,比如从节点重定向回索引或任何原始路由(你可以将它们添加为参数等)。然后,有一个 Angular 服务,如果有身份验证数据,总是会与后端进行检查。

或者您可以让您的节点后端嵌入 Angular 的index.html 或您正在使用的任何页面中的信息。你知道,老派的服务器端注入数据可能是带有ejsjade 之类的脚本标签。它会更快,但我仍然不会在客户端(或服务器)上盲目信任它,并且可能会在后台进行仔细检查。

【讨论】:

  • 答案也帮助了我。写得好,谢谢 Zlatko。
【解决方案2】:

您在代码中执行的操作调用了对您自己的服务器的 GET 请求。我根本看不到任何页面重定向。

如果您想将用户重定向到外部网站,您需要将用户发送到那里:

来自 HTML 文件:

<a href="http://example.com">Link to steam</a>

从您的组件 .ts 文件中:

window.location.href = 'http://www.example.com'

如果您想将用户重定向到您网站上的另一个页面,您需要使用 Angular 路由器:

来自 HTML 文件:

<a routerLink="/component-one">Component One</a>

来自您的组件 .ts 文件:

this.router.navigate(['/component-one']);

所以你的组件现在变成了:

import { Component } from '@angular/core';
import { AuthenticationService } from './authentication.service';
import { Router } from '@angular/router';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [ AuthenticationService ] // This should be provided by the module, not the component
})
export class AppComponent {

  constructor(private authService: AuthenticationService, private router: Router) { }

  login(): void {
    this.authService.login().subscribe(data => {
      alert(data);
      this.router.navigate('/to-some-page');
    });
  }

}

更多示例可以通过简单的Google search 找到,如下所示 https://coryrylan.com/blog/introduction-to-angular-routing

【讨论】:

  • 重定向是通过 Passport 的authenticate 方法自动完成的。
【解决方案3】:

据我所知,您从未将用户引导至 Steam 页面。您对 klong 的评论:“重定向是通过 Passport 完成的”。这可能是,但是您永远不会将用户发送到特定页面。您只是在前端制作一个 GET 请求表单。

关于同源策略错误。我认为这是由 Passport 引起的,因为您在 express 服务器上使用了 Cors。我认为最好的解决方案是创建一个简单的代理。如果您使用 CLI,则可以使用 this example

【讨论】:

    【解决方案4】:

    首先,您不会将登录请求发送到快递后端。您必须将登录请求发送到 steam oidc 授权端点。看看 Steam 怎么说:

    使用 OpenID 时,用户从第三方网站的网络浏览器开始。当用户希望使用 OpenID 将其帐户登录/链接到该网站时,该网站会将用户引导至 Steam 社区网站上的登录表单。一旦用户输入了他们的 Steam 登录凭据,用户的网络浏览器就会自动重定向回第 3 方网站,并在返回 URL 中附加一些额外的 OpenID 特定数据。然后,该站点的 OpenID 库可以使用这些数据来验证并获取用户的 SteamID。

    它叫做 Oidc,幸运的是你有两个很好的 Angular 库。 This (Recommended)This

    您的快速服务器需要做的是在请求之前验证从您的 Angular 客户端收到的令牌。我对 express 不是很熟悉,但我敢肯定至少有几个库供您验证令牌。

    您还需要对此主题进行更多研究。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-03
      • 1970-01-01
      • 2013-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多