如何使用 Typescript 在 Angular 2 中使用 Google 实现登录

Posted

技术标签:

【中文标题】如何使用 Typescript 在 Angular 2 中使用 Google 实现登录【英文标题】:How to implement SignIn with Google in Angular 2 using Typescript 【发布时间】:2016-12-15 05:36:31 【问题描述】:

我一直在尝试在单独的登录组件中以 Angular 2 实现使用 Google 登录。我无法使用 Google https://developers.google.com/identity/sign-in/web/sign-in 中提供的文档来实现它

当我在 index.html 文件中声明我的脚本标签和谷歌回调函数时,谷歌登录确实有效。但是我需要一个单独的组件才能使用 google 按钮呈现登录并在其中接收回调以进一步处理为用户接收到的访问令牌

【问题讨论】:

Google Sign-In for Websites and Angular 2 using Typescript的可能重复 在这里找到另一个更短的解决方案:***.com/questions/39880243/… 【参考方案1】:

在你的应用程序index.html文件中添加这一行

索引.html

<script src="https://apis.google.com/js/platform.js" async defer></script>

Component.ts 文件

declare const gapi: any;
  public auth2: any;
  public googleInit() 
    gapi.load('auth2', () => 
      this.auth2 = gapi.auth2.init(
        client_id: 'YOUR_CLIENT_ID.apps.googleusercontent.com',
        cookiepolicy: 'single_host_origin',
        scope: 'profile email'
      );
      this.attachSignin(document.getElementById('googleBtn'));
    );
  
  public attachSignin(element) 
    this.auth2.attachClickHandler(element, ,
      (googleUser) => 

        let profile = googleUser.getBasicProfile();
        console.log('Token || ' + googleUser.getAuthResponse().id_token);
        console.log('ID: ' + profile.getId());
        console.log('Name: ' + profile.getName());
        console.log('Image URL: ' + profile.getImageUrl());
        console.log('Email: ' + profile.getEmail());
        //YOUR CODE HERE


      , (error) => 
        alert(JSON.stringify(error, undefined, 2));
      );
  

ngAfterViewInit()
      this.googleInit();

模板 html 文件

<button id="googleBtn">Google</button>

在Plunker查看演示

【讨论】:

感谢 :) Quaffer 和 @Steel 的额外输入。 顺便说一句。没有 angularJS 2。有 Angular 2+,还有 AngularJS 低于 2 您好 Pravesh,您的代码工作正常,但我收到错误为“用户关闭弹出窗口”。所以我无法得到响应。您能建议任何帮助吗? 您的代码运行良好。但是登录后我想在主页上重定向。我如何做到这一点。代码::> this._router.navigate(['/home']); // 不工作 此代码有效,但如果用户在浏览器中单击返回或在其他一些路由问题期间,该按钮将失效。【参考方案2】:

src/index.html

在您应用的 index.html 文件中,您需要将其添加到 &lt;head&gt; 部分:

<meta name="google-signin-scope" content="profile email">
<meta name="google-signin-client_id" content="YOUR_CLIENT_ID.apps.googleusercontent.com">
<script src="https://apis.google.com/js/platform.js" async defer></script>

打字/浏览器/环境/gapi/

您需要在您的输入中添加gapi 和gapi.auth2:

npm install --save @types/gapi.auth2
npm install --save @types/gapi

(请参阅 borysn 的 question 以更好地理解这一点)。

src/app/+login/login.component.ts

这是我的组件的文件,这里你需要使用ngAfterViewInit() 来使用gapi 并获取授权。你可以在这里developers.google...sign-in/web/build-button

例如,这是我的模板:

<div id="my-signin2"></div>

和登录功能:

ngAfterViewInit() 
    gapi.signin2.render('my-signin2', 
        'scope': 'profile email',
        'width': 240,
        'height': 50,
        'longtitle': true,
        'theme': 'light',
        'onsuccess': param => this.onSignIn(param)
    );


public onSignIn(googleUser) 
    var user : User = new User();

    ((u, p) => 
        u.id            = p.getId();
        u.name          = p.getName();
        u.email         = p.getEmail();
        u.imageUrl      = p.getImageUrl();
        u.givenName     = p.getGivenName();
        u.familyName    = p.getFamilyName();
    )(user, googleUser.getBasicProfile());

    ((u, r) => 
        u.token         = r.id_token;
    )(user, googleUser.getAuthResponse());

    user.save();
    this.goHome();
;

更新:一段时间后,考虑到 cmets,这个答案需要一个小的更新。

【讨论】:

您也可以使用npm install --save @types/gapi.auth2 npm install --save @types/gapi 而不是手动将名称空间添加到您的打字中我不知道这是否是您的意思,我只是从打字稿和角度开始并发现这种添加类型的方式 我玩过那个例子,发现模板中的(data-onsuccess)="onSignIn"没有被使用。注册回调在ngAfterViewInit 中完成。无论如何,回调都不会触发模板的重新渲染(我还在模板中打印了登录的配置文件),因为调用发生在 Angular 区域之外。确保注入 NgZone 并使用 zone.run(() =&gt; /* Updates here */) 包装更新。 这永远不会被解雇(data-onsuccess)="onSignIn" 如果有人让它工作,我很乐意阅读实现。谢谢。 如果我不想在元标记中添加 googleClientId 怎么办? @Smit,public googleClientId 是安全有效的做法。如果您出于某种原因想要隐藏它,则必须将身份验证通信委托回您的服务器,从而增加更多请求和延迟。使用 public googleClientId,所有这些工作都是在客户端浏览器和 google api 之间完成的,根本不涉及您的服务器。只有您受保护的 API 调用会传递 JWT 令牌,并且服务器可以对其进行验证(也无需与 google 进行额外的通信)。【参考方案3】:

带有箭头 (=&gt;) 函数的词法范围使 let that = this; 的使用变得不必要。

Pravesh 示例的更清晰 版本,不需要that 范围界定工作,将是:

Index.html

<script src="https://apis.google.com/js/platform.js" async defer></script>

Component.ts

declare const gapi: any;

@Component(
  selector: 'google-signin',
  template: '<button id="googleBtn">Google Sign-In</button>'
)
export class GoogleSigninComponent implements AfterViewInit 

  private clientId:string = 'YOUR_CLIENT_ID.apps.googleusercontent.com';

  private scope = [
    'profile',
    'email',
    'https://www.googleapis.com/auth/plus.me',
    'https://www.googleapis.com/auth/contacts.readonly',
    'https://www.googleapis.com/auth/admin.directory.user.readonly'
  ].join(' ');

  public auth2: any;

  public googleInit()         
    gapi.load('auth2', () => 
      this.auth2 = gapi.auth2.init(
        client_id: this.clientId,
        cookiepolicy: 'single_host_origin',
        scope: this.scope
      );
      this.attachSignin(this.element.nativeElement.firstChild);
    );
  

  public attachSignin(element) 
    this.auth2.attachClickHandler(element, ,
      (googleUser) => 
        let profile = googleUser.getBasicProfile();
        console.log('Token || ' + googleUser.getAuthResponse().id_token);
        console.log('ID: ' + profile.getId());
        // ...
      , function (error) 
        console.log(JSON.stringify(error, undefined, 2));
      );
  

  constructor(private element: ElementRef) 
    console.log('ElementRef: ', this.element);
  

  ngAfterViewInit() 
    this.googleInit();
  

模板

<div id="googleBtn">Google</div>

Working Plnkr

【讨论】:

根据 ng2,这似乎是一种更清洁的方法 嗨史蒂夫戈麦斯,我在使用此代码“无效的 cookiePolicy”后收到错误消息。你有什么解决办法吗? 嗨史蒂夫戈麦斯,我收到错误消息“无效的 cookiePolicy”。你有什么解决办法吗? @SandipMoradiya 他们的 api 从 cookiepolicy 更改为 cookie_policy【参考方案4】:

还有另一种与google联系的方式:

index.html 中添加这些行:

<meta name="google-signin-client_id" content="YOUR-GOOGLE-APP-ID.apps.googleusercontent.com">
<script src="https://apis.google.com/js/platform.js"></script>

然后这里是在组件(或服务,如果你愿意)上编写的示例代码:

import Component from "@angular/core";
declare const gapi : any;


@Component( ... )
export class ComponentClass 
   constructor() 
      gapi.load('auth2', function () 
         gapi.auth2.init()
      );
   

   googleLogin() 
      let googleAuth = gapi.auth2.getAuthInstance();
      googleAuth.then(() => 
         googleAuth.signIn(scope: 'profile email').then(googleUser => 
            console.log(googleUser.getBasicProfile());
         );
      );
   

【讨论】:

【参考方案5】:

截至目前,Angular 的最新版本来了,而且我们大多使用 Angular 4/5/6,所以想提供这个简单的解决方案来通过社交登录以便真正想要它的人

Angular 4/5/6 社交登录

在您的 AppModule 中,导入 SocialLoginModule

import  SocialLoginModule, AuthServiceConfig  from "angularx-social-login";
import  GoogleLoginProvider, FacebookLoginProvider, LinkedInLoginProvider from "angularx-social-login";


let config = new AuthServiceConfig([
  
    id: GoogleLoginProvider.PROVIDER_ID,
    provider: new GoogleLoginProvider("Google-OAuth-Client-Id")
  ,
  
    id: FacebookLoginProvider.PROVIDER_ID,
    provider: new FacebookLoginProvider("Facebook-App-Id")
  ,
  
    id: LinkedInLoginProvider.PROVIDER_ID,
    provider: new FacebookLoginProvider("LinkedIn-client-Id", false, 'en_US')
  
]);

export function provideConfig() 
  return config;


@NgModule(
  declarations: [
    ...
  ],
  imports: [
    ...
    SocialLoginModule
  ],
  providers: [
    
      provide: AuthServiceConfig,
      useFactory: provideConfig
    
  ],
  bootstrap: [...]
)
export class AppModule  

并在你的组件中使用它

通过导入以下模块

import  AuthService  from "angularx-social-login";
import  SocialUser  from "angularx-social-login";

如需完整参考,您可以查看他们的Github

demo 的页面非常简单

【讨论】:

只有这个解决方案适用于带有 npm 包 angular5-social-login 的 Angular 6 我已经实现了上述内容并且工作正常。我需要打电话给accounts.google.com/logout,让用户完全退出谷歌。由于 AuthService 将使实例为空并仅记录我的应用程序,因此我的要求要求退出谷歌。我应该如何使用我提到的链接来实现相同的目标,即accounts.google.com/logout 由于我们没有后端服务所以这个服务只是管理前端。你可以手动做,检查本地存储,你会得到一些东西或登录后使用标志并保存它到本地存储并从那里注销。 如果我从服务中动态获取“Google-OAuth-Client-Id”,我该如何实现?我花了一天时间尝试,但没有成功。【参考方案6】:

这对我来说几乎没有任何效果,因为我想要谷歌制作的谷歌按钮。 @mathhew eon 的代码有效,但没有使用他们的按钮。

所以我把谷歌数据成功功能扔到窗口上,它工作得非常完美!如果用户已经登录,它还有一个额外的优势,它会自动调用 googleLogin 函数。

html

<div class="g-signin2" data-onsuccess="googleLogin" data-theme="dark"></div>

在你的 index.html 中把它放在头部:

<meta name="google-signin-client_id" content="YOUR-GOOGLE-APP-ID.apps.googleusercontent.com">
<meta name="google-signin-scope" content="profile email AND WHATEVER OTHER SCOPES YOU WANT">
<script src="https://apis.google.com/js/platform.js" async defer></script>

然后在你的 ngOnInit 中

ngOnInit() 
    (window as any).googleLogin = this.googleLogin

public googleLogin(userInfo) 
    console.log(userInfo)

【讨论】:

【参考方案7】:

除了我添加之外,之前的回答都是一样的

声明 var gapi: any;否则会报错。

src/index.html

在您的应用程序的 index.html 文件中,您需要在以下部分添加:

<meta name="google-signin-scope" content="profile email">
<meta name="google-signin-client_id" content="YOUR_CLIENT_ID.apps.googleusercontent.com">
<script src="https://apis.google.com/js/platform.js" async defer></script>

打字/浏览器/环境/gapi/

您需要在您的打字中添加 gapi 和 gapi.auth2:

npm install --save @types/gapi.auth2
npm install --save @types/gapi

(请参阅这个 borysn 的问题以更好地理解这一点)。

src/app/+login/login.component.ts

这是我的组件的文件,这里你需要使用 ngAfterViewInit() 来使用 gapi 并获取 auth。您可以在developers.google...sign-in/web/build-button 关注实现

例如,这是我的模板:

<div id="my-signin2"></div>

和登录功能:

 declare var gapi: any;

ngAfterViewInit() 
   gapi.signin2.render('my-signin2', 
      'scope': 'profile email',
      'width': 240,
      'height': 50,
      'longtitle': true,
      'theme': 'light',
      'onsuccess': param => this.onSignIn(param)
  );


public onSignIn(googleUser) 
   var user : User = new User();

      ((u, p) => 
         u.id            = p.getId();
         u.name          = p.getName();
         u.email         = p.getEmail();
         u.imageUrl      = p.getImageUrl();
         u.givenName     = p.getGivenName();
         u.familyName    = p.getFamilyName();
      )(user, googleUser.getBasicProfile());

      ((u, r) => 
         u.token         = r.id_token;
      )(user, googleUser.getAuthResponse());

      user.save();
      this.goHome();
;

【讨论】:

不是所有的东西都是一样的,除了 gapi。您还在 gapi.singin2 上添加了渲染方法,这对我来说是一个保护程序。谢谢。

以上是关于如何使用 Typescript 在 Angular 2 中使用 Google 实现登录的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Angular 的 Typescript 中使用数组

如何使用 Typescript 在 Angular 2 中使用 Google 实现登录

如何使用 Angular 2 / Typescript 限制输入字段中的特殊字符

如何在 Angular 2 / Typescript 中声明全局变量? [关闭]

如何使用 Jasmine 为私有方法编写 Angular / TypeScript 单元测试

如何在 Angular 5 中从 Typescript 调用 JavaScript 函数?