如何在Ember.js中实现谷歌登录认证(无需Torii)
无需Torii的Ember.js谷歌登录认证实现方案
核心思路
直接基于谷歌官方的Google Identity Services(原Google Sign-In JavaScript API),结合Ember.js的组件化特性或初始化器实现登录逻辑,无需依赖停更的Torii;若需要会话管理,可搭配最新版的ember-simple-auth(完全适配当前Ember版本)。
完整实现步骤
1. 修正index.html配置
你现有配置已包含Client ID和谷歌脚本,仅需调整注释位置避免HTML解析问题:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Signin</title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Google OAuth2 Client ID --> <meta name="google-signin-client_id" content="93818-913ria6b3vcjh2.apps.googleusercontent.com"> {{content-for "head"}} <link integrity="" rel="stylesheet" href="{{rootURL}}assets/vendor.css"> <link integrity="" rel="stylesheet" href="{{rootURL}}assets/signin.css"> {{content-for "head-footer"}} </head> <body> {{content-for "body"}} <!-- Google Identity Service 加载脚本 --> <script src="https://apis.google.com/js/platform.js" async defer></script> <script src="{{rootURL}}assets/vendor.js"></script> <script src="{{rootURL}}assets/signin.js"></script> {{content-for "body-footer"}} </body> </html>
2. 组件化登录按钮(推荐方案)
将登录逻辑封装为Ember组件,避免全局函数污染,同时方便复用:
组件逻辑文件 app/components/google-login-button.js
import Component from '@glimmer/component'; import { action } from '@ember/object'; import { inject as service } from '@ember/service'; export default class GoogleLoginButtonComponent extends Component { @service session; // 若使用ember-simple-auth,注入会话服务 constructor() { super(...arguments); // 初始化谷歌认证实例 window.gapi.load('auth2', () => { window.gapi.auth2.init({ client_id: '93818-913ria6b3vcjh2.apps.googleusercontent.com' }); }); } @action async handleSignIn(googleUser) { // 获取用户核心信息 const profile = googleUser.getBasicProfile(); console.log('用户ID:', profile.getId()); console.log('邮箱:', profile.getEmail()); console.log('用户名:', profile.getName()); console.log('头像地址:', profile.getImageUrl()); // 获取ID Token(用于后端验证身份) const idToken = googleUser.getAuthResponse().id_token; // 可选:用ember-simple-auth保存会话 await this.session.authenticate('authenticator:google', idToken); } @action handleSignOut() { const auth2 = window.gapi.auth2.getAuthInstance(); auth2.signOut().then(() => { // 可选:销毁ember-simple-auth会话 this.session.invalidate(); }); } }
组件模板文件 app/templates/components/google-login-button.hbs
<h2><center>使用谷歌账号登录</center></h2> <div class="g-signin2" data-onsuccess={{this.handleSignIn}}></div> {{#if this.session.isAuthenticated}} <button {{on "click" this.handleSignOut}}>退出登录</button> {{/if}}
在页面中使用组件
在需要登录功能的模板中引入组件:
<GoogleLoginButton />
3. 自定义ember-simple-auth认证器(可选)
若需要会话持久化和权限管理,创建谷歌专属认证器:app/authenticators/google.js
import BaseAuthenticator from 'ember-simple-auth/authenticators/base'; export default class GoogleAuthenticator extends BaseAuthenticator { async authenticate(idToken) { // 调用后端API验证ID Token合法性,返回用户会话数据 const response = await fetch('/api/auth/google', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id_token: idToken }) }); const data = await response.json(); // 返回会话数据,ember-simple-auth会自动存储到本地 return { token: data.token, user: data.user }; } async restore(data) { // 页面刷新后验证会话有效性 if (data.token) return data; throw new Error('会话已失效'); } async invalidate() { // 可选:调用后端接口销毁服务器端会话 await fetch('/api/auth/logout', { method: 'POST' }); } }
4. 简化版:全局函数获取用户信息
若不想封装组件,可通过Ember初始化器定义全局登录回调:app/initializers/google-auth.js
import { registerDestructor } from '@ember/destroyable'; export function initialize(application) { // 定义谷歌登录成功回调 window.onSignIn = function(googleUser) { const profile = googleUser.getBasicProfile(); // 直接获取并处理用户信息 console.log('用户邮箱:', profile.getEmail()); console.log('用户名:', profile.getName()); const idToken = googleUser.getAuthResponse().id_token; // 此处可添加登录逻辑(如调用后端、存储到本地) }; // 应用销毁时清理全局函数 registerDestructor(application, () => { delete window.onSignIn; }); } export default { initialize };
关键注意事项
- 确保谷歌开发者控制台已配置正确的JavaScript授权来源(如
http://localhost:4200) - ID Token必须通过后端验证,禁止仅依赖前端数据信任用户身份
- 若使用ember-simple-auth,需确保安装的是最新稳定版(适配Ember 3.x及以上版本)
内容的提问来源于stack exchange,提问作者hariharan baskaran
相关产品推荐
相关产品推荐

