jjzjj

java - 使用现有 API 的 FB/Google 客户端登录(Ionic)

coder 2024-03-29 原文

我的堆栈是:

  • ionic 2
  • Java Spring
  • JWT 认证

并且我想在我的应用程序中使用相应的 cordova 插件实现一个社交登录按钮(Facebook、谷歌等),用于登录用户并在我现有的自定义服务器端 API 上验证他并存储他/她的数据.我找不到任何关于如何执行此操作的好教程。

我希望我的用户使用随 secret 码保存在数据库中并能够从我的应用程序登录。

我在想一些事情:

(客户端)

FB.login(function(userDetailsAndToken) {
    myBackendAPI.socialLogin(userDetailsAndToken).then(function(user) {
        //Successfully logged in with Facebook!
        this.user = user;
    }
}

在后端(Java Spring):

@PostMapping("/social/account")
public ResponseEntity socialAccount(@Valid @RequestBody FacebookDTO facebookDTO) {
    validateSocialUser(facebookDTO);

    //if user exists return invalid etc.
    Optional<User> existingUser = userRepository.findOneByEmail(facebookDTO.getEmail());
    if (existingUser.isPresent()) {
        return ResponseEntity.badRequest();
    }

    //User doesn't exist. Proceed with login 
    //map from social to my User entity
    User user = socialMapper.toEntity(facebookDTO);

    userService
        .createUser(user.getLogin(), user.getPassword(),
            user.getFirstName(), user.getLastName(),
            user.getEmail().toLowerCase(), user.getImageUrl(),
            user.getLangKey());
    return new ResponseEntity<>(HttpStatus.CREATED);
}

这可能且安全吗?关于如何实现这一目标的任何好的资源/库或指南?

最佳答案

这是一个关于使用 FB 和 Google Auth 的示例演示,但我不是 Java 背景的,所以您只会找到客户端解决方案。

服务

让我们来实现登录功能的逻辑。在 oauth 文件夹中创建一个 oauth.service.ts 文件并在其中粘贴以下代码:

import { Injectable, Injector } from '@angular/core';
import { FacebookOauthProvider } from './facebook/facebook-oauth.provider';
import { IOathProvider } from './oauth.provider.interface';
import { GoogleOauthProvider } from './google/google-oauth.provider';
import { OAuthToken } from './models/oauth-token.model';
@Injectable()
export class OAuthService {
    private oauthTokenKey = 'oauthToken';
    private injector: Injector;
constructor(injector: Injector) {
        this.injector = injector;
    }
login(source: string): Promise {
        return this.getOAuthService(source).login().then(accessToken => {
            if (!accessToken) {
                return Promise.reject('No access token found');
            }
let oauthToken = {
                accessToken: accessToken,
                source: source
            };
            this.setOAuthToken(oauthToken);
            return oauthToken;
        });
    }
getOAuthService(source?: string): IOathProvider {
        source = source || this.getOAuthToken().source;
        switch (source) {
            case 'facebook':
                return this.injector.get(FacebookOauthProvider);
            case 'google':
                return this.injector.get(GoogleOauthProvider);
            default:
                throw new Error(`Source '${source}' is not valid`);
        }
    }
setOAuthToken(token: OAuthToken) {
        localStorage.setItem(this.oauthTokenKey, JSON.stringify(token));
    }
getOAuthToken(): OAuthToken {
        let token = localStorage.getItem(this.oauthTokenKey);
        return token ? JSON.parse(token) : null;
    }
}

身份验证提供程序和 token 接口(interface) 正如我们已经提到的,IOathProvider 应该包含一个 login() 函数。因此,我们应该设置以下接口(interface)作为 IOathProvider 对象的抽象类型/模型。在 oauth 文件夹中创建一个 oauth.provider.interface.ts 文件,并在其中包含以下行:

export interface IOathProvider {
    login(): Promise;
}

Facebook 和 Google 身份验证服务

下一步,我们应该为我们的应用程序拥有的每个身份验证提供程序实现服务,即 FacebookOauthProviderGoogleOauthProvider

安装依赖

此时 ng2-cordova-oauth 库就派上用场了。我们可以通过执行命令来安装它: npm install ng2-cordova-oauth --save

此外,我们的应用依赖于 Cordova InAppBrowser 插件。我们将安装它:

ionic 插件添加 cordova-plugin-inappbrowser

不要忘记将 cordova-plugin-inappbrowser 也包含在您的 package.json 文件中,这样它就可以在您从头开始安装项目的任何时候与其他插件一起安装。

实现 Facebook 和 Google 身份验证提供程序

让我们在 oauth/facebook/路径 下创建 facebook-oauth.provider.ts 文件。在此文件中,将代码包含在片段中:

 import { Injectable } from '@angular/core';
    import { Http } from '@angular/http';
    import { IOathProvider } from '../oauth.provider.interface';
    import { CordovaOauth } from 'ng2-cordova-oauth/oauth';
    import { Facebook } from 'ng2-cordova-oauth/provider/facebook';
    import { Config } from '../../../config';
    interface ILoginResponse {
        access_token: string;
    }
    @Injectable()
    export class FacebookOauthProvider implements IOathProvider {
        private cordovaOauth: CordovaOauth;
        private http: Http;
        private config: Config;
        private facebook: Facebook;
    constructor(http: Http, config: Config) {
            this.http = http;
            this.config = config;
            this.facebook = new Facebook({ clientId: config.facebook.appId, appScope: config.facebook.scope });
            this.cordovaOauth = new CordovaOauth();
        }
    login(): Promise {
            return this.cordovaOauth.login(this.facebook)
                .then((x: ILoginResponse) => x.access_token);
        }
    }

同样,使用 ng2-cordova-oauth 库 提供的 CordovaOauth 对象,我们将使用自己的 Google 身份验证提供程序 login() 函数。但是,我们在这里从 Config 传递了另一个 clientId,它对应于我们使用 Google Developer Console 配置的应用程序。 因此,创建一个 google-oauth.provider.ts 文件并粘贴以下行:

import { Injectable } from '@angular/core';
import { IOathProvider } from '../oauth.provider.interface';
import { OAuthProfile } from '../models/oauth-profile.model';
import { CordovaOauth } from 'ng2-cordova-oauth/oauth';
import { Google } from 'ng2-cordova-oauth/provider/google';
import { Config } from '../../../config';
import { Http } from '@angular/http';
interface ILoginResponse {
    access_token: string;
}
@Injectable()
export class GoogleOauthProvider implements IOathProvider {
    private http: Http;
    private config: Config;
    private cordovaOauth: CordovaOauth;
    private google: Google;
constructor(http: Http, config: Config) {
        this.http = http;
        this.config = config;
        this.google = new Google({ clientId: config.google.appId, appScope: config.google.scope });
        this.cordovaOauth = new CordovaOauth();
    }
login(): Promise {
        return this.cordovaOauth.login(this.google).then((x: ILoginResponse) => x.access_token);
    }
getProfile(accessToken: string): Promise {
        let query = `access_token=${accessToken}`;
        let url = `${this.config.google.apiUrl}userinfo?${query}`;
return this.http.get(url)
            .map(x => x.json())
            .map(x => {
                let name = x.name.split(' ');
                return {
                    firstName: name[0],
                    lastName: name[1],
                    email: x.email,
                    provider: 'google'
                };
            })
            .toPromise();
    }
}

全部归功于 this文章,你可以找到Working Code在 Github 上。我没有涵盖整个教程,只有该教程的部分(Google 和 Facebook)。即我们需要安装什么插件以及如何使用 TypeScript ,如果您还需要那么您可以引用该教程

关于java - 使用现有 API 的 FB/Google 客户端登录(Ionic),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45826138/

有关java - 使用现有 API 的 FB/Google 客户端登录(Ionic)的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  10. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

随机推荐