GVKun编程网logo

两步验证杀手锏:Java 接入 Google 身份验证器实战(谷歌验证码java)

1

如果您想了解两步验证杀手锏:Java接入Google身份验证器实战的相关知识,那么本文是一篇不可错过的文章,我们将对谷歌验证码java进行全面详尽的解释,并且为您提供关于Cordova:使用模拟器x8

如果您想了解两步验证杀手锏:Java 接入 Google 身份验证器实战的相关知识,那么本文是一篇不可错过的文章,我们将对谷歌验证码java进行全面详尽的解释,并且为您提供关于Cordova:使用模拟器 x86 (google play) 不适用于 x86 google apis 和 x86_64 google apis、GAS:将来自 Google Drive 中多个 Google Sheets 文档工作簿的数据合并到一个工作簿中 获取特定列:移动文件:如何在 Google 云端硬盘中移动文件、Google API 的 Google OAuth 2.0 范围与 Google Cloud 上的 IAM 中的角色和权限有何不同? OAuth范围IAM遗产?、Google App Script/Javascript - 无法使用 Google App Script 循环到 Google 电子表格中的列末尾的有价值的信息。

本文目录一览:

两步验证杀手锏:Java 接入 Google 身份验证器实战(谷歌验证码java)

两步验证杀手锏:Java 接入 Google 身份验证器实战(谷歌验证码java)

两步验证

大家应该对两步验证都熟悉吧?如苹果有自带的两步验证策略,防止用户账号密码被盗而锁定手机进行敲诈,这种例子屡见不鲜,所以苹果都建议大家开启两步验证的。

Google 的身份验证器一般也是用于登录进行两步验证,和苹果的两步验证是同样的道理。只不过 Google 的身份验证器用得更多更广泛,如 GitHub 的两步验证都是基于 Google 身份验证器。

Google Authenticator 简介

Google Authenticator 身份验证器是一款基于时间与哈希的一次性密码算法的两步验证软件令牌,用户需要下载手机 APP(Authenticator),该手机 APP 与网站进行绑定,当网站验证完用户名和密码之后会验证此 APP 上对应生成的 6 位验证码数字,验证通过则成功登录,否则登录失败。

Google Authenticator 使用

我们来看下 Github 上的使用 Google 身份验证器开启两步验证的应用。

如图所示,默认 Github 是没有开启两步验证的,点击设置按钮进行设置。

Github 提供了基于 APP (谷歌身份验证器)和短信验证码两种两步验证的方式,我们选择第一种谷歌身份验证器。

进入第一种验证模式,接下来展示了一堆的恢复码,用来当 APP 验证器不能工作的紧急情况使用。把它们保存起来,然后点击下一步。

这个就是身份验证器的关键了,下载 Google 的 Authenticator APP,然后扫描这个二维码进行绑定。

绑定之后,APP Github 模块下面会显示一个 6 位的验证码,把它输入到上面那个框里面就行了。

如下图所示,已经成功开启两步验证了。

接下来我们退出 Github 再重新登录,页面就会提示要输入 Google 的身份验证器验证码了,如果 APP 不能正常工作,最下方还能通过之前保存下来的恢复码进行登录。

好了,Google Authenticator 使用就到这里,那它是如何工作的,它是什么原理呢?我们的网站、APP 如何接入 Google Authenticator,接下来我们一一拉开谜底。

Google Authenticator 工作流程

实际上 Google Authenticator 采用的是 TOTP 算法(Time-Based One-Time Password,即基于时间的一次性密码),其核心内容包括以下三点。

1、安全密钥

是客户端和服务端约定的安全密钥,也是手机端 APP 身份验证器绑定(手机端通过扫描或者手输安全密钥进行绑定)和验证码的验证都需要的一个唯一的安全密钥,该密钥由加密算法生成,并最后由 Base32 编码而成。

2、验证时间

Google 选择了 30 秒作为时间片,T的数值为 从Unix epoch(1970年1月1日 00:00:00)来经历的 30 秒的个数,所以在 Google Authenticator 中我们可以看见验证码每个 30 秒就会刷新一次。

更详细原理参考:

https://blog.seetee.me/post/2...

3、签署算法

Google 使用的是 HMAC-SHA1 算法,全称是:Hash-based message authentication code(哈希运算消息认证码),它是以一个密钥和一个消息为输入,生成一个消息摘要作为输出,这里以 SHA1 算法作为消息输入。

使用 HMAC 算法是因为只有用户本身知道正确的输入密钥,因此会得到唯一的输出,其算法可以简单表示为:

hmac = SHA1(secret + SHA1(secret + input))

事实上,TOTP 是 HMAC-OTP(基于HMAC的一次密码生成)的超集,区别是 TOTP 是以当前时间作为输入,而HMAC-OTP 则是以自增计算器作为输入,该计数器使用时需要进行同步。

Google Authenticator 实战

知道上面的原理,我们就可以来应用实战了。

/**
 * 微信公众号:Java技术栈
 */
public class AuthTest {

    @Test
    public void genSecretTest() {
        String secret = GoogleAuthenticator.generateSecretKey();
        String qrcode = GoogleAuthenticator.getQRBarcodeURL("Java技术栈", "javastack.cn", secret);
        System.out.println("二维码地址:" + qrcode);
        System.out.println("密钥:" + secret);
    }

    @Test
    public void verifyTest() {
        String secret = "ZJTAQGLVOZ7ATWH2";
        long code = 956235;
        GoogleAuthenticator ga = new GoogleAuthenticator();
        boolean r = ga.verifCode(secret, code);
        System.out.println("是否正确:" + r);
    }
}

第一个方法是生成密钥和一个扫描二维码绑定的URL。

第二个方法是根据密钥和验证码进行验证。

这里仅提供一下 GoogleAuthenticator 类的源码逻辑参考。

http://awtqty-zhang.iteye.com...

如果有收获欢迎点赞转发,也可以留言发表你的疑问和看法。

教程:史上最强 Spring Boot & Cloud 教程汇总

工具:推荐一款在线创作流程图、思维导图软件

image

Cordova:使用模拟器 x86 (google play) 不适用于 x86 google apis 和 x86_64 google apis

Cordova:使用模拟器 x86 (google play) 不适用于 x86 google apis 和 x86_64 google apis

如何解决Cordova:使用模拟器 x86 (google play) 不适用于 x86 google apis 和 x86_64 google apis

该项目在浏览器中完美运行,但是当我在 x86 (google play) 模拟器中运行它时,除了 MapBox 地图外,一切正常,为了修复它,我制作了另一个测试项目并对其进行了一些尝试以发现MapBox 仅适用于 Google Api(x86 或 x86_64),因此我尝试使用带有 x86 Google Api 和 x86_64 Google Api 的模拟器启动我的主项目并抛出此错误:

channel_MVC.js:12 Uncaught SyntaxError: Unexpected token =

wall_MVC.js:11 Uncaught SyntaxError: Unexpected token =

index.js:93 Uncaught ReferenceError: ControllerWall is not defined
    at Channel.onDeviceReady (index.js:93)
    at Channel.fire (cordova.js:872)
    at cordova.js:232

这是关于错误的一段代码:

Channel_MVC:

class ModelChannel {
  constructor() {

    this._posts = []
    this._channelName = ''''

  }

  savePosts = async (response,channelName) => {.  //line 12: error here
    ...
    };

   ...

  }

wall_MVC:

class ModelWall {
  constructor() {

    this._channels = []
      
  }

  saveChannels = (response) => { //line 11: error here
    ...
  }

索引:

const app = new ControllerWall(new ModelWall(),new ViewWall())
app.model.refreshWallModel()

我试图通过像这样改变所有函数的格式来解决这个问题:

//From this      
savePosts = async (response,channelName) => {.  //line 12: error here
        ...
        };

//To this
async savePosts (response,channelName) {
 ...
}

但这只会导致在构造函数中定义视图和模型时抛出错误,bat 不能被类中的任何其他函数访问:

class ControllerWall {
  constructor(model,view) {
    this.model = model
    this.view = view


    //this.onChannelListChanged(this.model._channels)

  
    this.model.bindOnChannelListChanged(this.onChannelListChanged)

    this.view.bindClickOnChannel(this.handleClickOnChannel)
    this.view.bindAddTodo(this.handleAddTodo)
    this.view.bindClickOnSettings(this.handleClickOnSettings)
    this.view.bindClickOnRefresh(this.handleCLickOnRefresh)

  }

  onChannelListChanged = (_channels) => {
    console.log("Channel list changed");
    this.view.displayChannels(_channels)  //Error: cannot displayChannels(_channels) of undefined
  }

  ...

}

我能做什么?

GAS:将来自 Google Drive 中多个 Google Sheets 文档工作簿的数据合并到一个工作簿中 获取特定列:移动文件:如何在 Google 云端硬盘中移动文件

GAS:将来自 Google Drive 中多个 Google Sheets 文档工作簿的数据合并到一个工作簿中 获取特定列:移动文件:如何在 Google 云端硬盘中移动文件

如何解决GAS:将来自 Google Drive 中多个 Google Sheets 文档工作簿的数据合并到一个工作簿中 获取特定列:移动文件:如何在 Google 云端硬盘中移动文件

我有多个工作表存储在一个文件夹中,我想要做的是通读每张工作表(特别是每张工作表的 D 列和 H 列),并通过将列映射到行来将数据附加到主文件中(与 Google 表单处理 Google 表格上的回复的方式相同)。

下一步是将读取的文件在读取后移动到另一个文件夹中。我已经做了一些挖掘并想出了下面的代码,但我遇到了一些挑战,希望能得到帮助:

(a) 将列数据(D 和 H)获取到主文件上的单行。 (b) 复制的文件被读取后移动到不同的文件夹中。

  1. function combinesheets() {
  2. const folder = DriveApp.getFolderById(copy_Folder_id)
  3. const filesIterator = folder.getFiles();
  4. const ws = SpreadsheetApp.openById(Stage_sheet_id);
  5. const ss = ws.getSheetByName("Project List");
  6. let combinedata = [];
  7. while(filesIterator.hasNext()){
  8. file = filesIterator.next();
  9. fileType = file.getMimeType();
  10. if(fileType === "application/vnd.google-apps.spreadsheet"){
  11. ssID = file.getId();
  12. const data = getDataFromSpreadsheet(ssID);
  13. combinedata.concat(data);
  14. }
  15. }
  16. ss.getRange(2,1,combinedata.length).setValues([combinedata]);
  17. }
  18. function getDataFromSpreadsheet(){
  19. var ss = SpreadsheetApp.openById(ssID);
  20. var ws = ss.getSheets()[0]
  21. var data = ws.getRange("A1:I" + ws.getLastRow()).getValues();
  22. data = data.reduce((acc,row) => acc.concat([row[3],row[7]]),[]);
  23. return data;
  24. }

解决方法

获取特定列:

您可以使用 reduce 将某些列中的值获取到单个数组中,然后可以将其添加到电子表格行中:

  1. function getDataFromSpreadsheet(ssID){
  2. var ss = SpreadsheetApp.openById(ssID);
  3. var ws = ss.getSheets()[0]
  4. var data = ws.getRange("A1:I" + ws.getLastRow()).getValues();// how do I get the columns I want here (D & H)
  5. data = data.reduce((acc,row) => acc.concat([row[3],row[7]]),[]);
  6. return data;
  7. }

然后,您需要将此数据添加到主工作表中。考虑到来自不同电子表格的 data 可能具有不同的长度,我建议在循环内部调用 appendRow 而不是在外部调用一次 setValues(因为,如果所有源列都不是相同的长度,您必须修改结果数组以使其大小相同;虽然可以这样做并且可以提高效率,但我不确定它是否值得,特别是如果您没有很多电子表格):

  1. function combinesheets() {
  2. const folder = DriveApp.getFolderById(Copy_Folder_id)
  3. const filesIterator = folder.getFiles();
  4. const ws = SpreadsheetApp.openById(Stage_sheet_id);
  5. const ss = ws.getSheetByName("Project List");
  6. while(filesIterator.hasNext()){
  7. file = filesIterator.next();
  8. fileType = file.getMimeType();
  9. if(fileType === "application/vnd.google-apps.spreadsheet"){
  10. ssID = file.getId();
  11. const data = getDataFromSpreadsheet(ssID);
  12. ss.appendRow(data);
  13. }
  14. }
  15. }

如果所有列的长度都相同,您可以改为这样做:

  1. function combinesheets() {
  2. const folder = DriveApp.getFolderById(Copy_Folder_id)
  3. const filesIterator = folder.getFiles();
  4. const ws = SpreadsheetApp.openById(Stage_sheet_id);
  5. const ss = ws.getSheetByName("Project List");
  6. let combinedata = [];
  7. while(filesIterator.hasNext()){
  8. file = filesIterator.next();
  9. fileType = file.getMimeType();
  10. if(fileType === "application/vnd.google-apps.spreadsheet"){
  11. ssID = file.getId();
  12. const data = getDataFromSpreadsheet(ssID);
  13. combinedata.push(data);
  14. }
  15. }
  16. ss.getRange(2,1,combinedata.length,combinedata[0].length).setValues(combinedata);
  17. }

最后,如果来自不同工作表的所有数据都应该在同一行,您可以改为这样做:

  1. function combinesheets() {
  2. const folder = DriveApp.getFolderById(Copy_Folder_id)
  3. const filesIterator = folder.getFiles();
  4. const ws = SpreadsheetApp.openById(Stage_sheet_id);
  5. const ss = ws.getSheetByName("Project List");
  6. let combinedata = [];
  7. while(filesIterator.hasNext()){
  8. file = filesIterator.next();
  9. fileType = file.getMimeType();
  10. if(fileType === "application/vnd.google-apps.spreadsheet"){
  11. ssID = file.getId();
  12. const data = getDataFromSpreadsheet(ssID);
  13. combinedata.concat(data);
  14. }
  15. }
  16. ss.getRange(2,combinedata.length).setValues([combinedata]);
  17. }

移动文件:

要将文件移动到另一个文件夹,您只需通过 DriveApp 检索文件和目标文件夹,然后调用:

  1. const file = DriveApp.getFileById("FILE_ID");
  2. const folder = DriveApp.getFolderById("FOLDER_ID");
  3. file.moveTo(folder);
,

你有两个问题。

如何在 Google 云端硬盘中移动文件

您只需要移动到的文件 ID 和文件夹 ID。浏览谷歌驱动器时,两者都可以在 URL 中看到。

enter image description here

这是一个执行它的函数:

  1. function changeLocation(folderToMoveToID,fileID) {
  2. var destinationFolder = DriveApp.getFolderById(folderToMoveToID);
  3. var theFileToMove = DriveApp.getFileById(fileID);
  4. theFileToMove.moveTo(destinationFolder);
  5. }

我稍后会尝试回答其他问题。

Google API 的 Google OAuth 2.0 范围与 Google Cloud 上的 IAM 中的角色和权限有何不同? OAuth范围IAM遗产?

Google API 的 Google OAuth 2.0 范围与 Google Cloud 上的 IAM 中的角色和权限有何不同? OAuth范围IAM遗产?

如何解决Google API 的 Google OAuth 2.0 范围与 Google Cloud 上的 IAM 中的角色和权限有何不同? OAuth范围IAM遗产?

我正在尝试解读来自 Error: Could not load the default credentials. context: firebase login:ci AND firebase auth:export 的以下错误消息中“范围”的含义:

  1. [2021-04-27T20:48:23.188Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
  2. [2021-04-27T20:48:26.208Z] Error: Could not load the default credentials. browse to https://cloud.google.com/docs/authentication/getting-started for more information.
  3. at GoogleAuth.getApplicationDefaultAsync (/home/node/.npm-global/lib/node_modules/firebase-tools/node_modules/google-auth-library/build/src/auth/googleauth.js:160:19)
  4. at processticksAndRejections (internal/process/task_queues.js:97:5)
  5. at runNextTicks (internal/process/task_queues.js:66:3)
  6. at listOnTimeout (internal/timers.js:518:9)
  7. at processtimers (internal/timers.js:492:7)
  8. at async GoogleAuth.getClient (/home/node/.npm-global/lib/node_modules/firebase-tools/node_modules/google-auth-library/build/src/auth/googleauth.js:502:17)
  9. at async GoogleAuth.getAccesstoken (/home/node/.npm-global/lib/node_modules/firebase-tools/node_modules/google-auth-library/build/src/auth/googleauth.js:524:24)
  10. Error: An unexpected error has occurred.

如果我了解什么是“范围”,我可能会知道在哪里设置它们。到目前为止,我只找到了一个地方可以在 IAM 中为我的用户设置角色和权限。

以下是我能找到的定义:

角色和权限 (source)

角色包含一组允许您执行 对 GCP 资源的具体操作。制作权限 对成员可用,包括用户、组和服务帐户, 您向成员授予角色。

范围(source、source)

访问范围是为您的用户指定权限的传统方法 实例。他们定义了请求中使用的默认 OAuth 范围 gcloud 工具或客户端库。

当我尝试使用由 firebase --debug auth:export 生成并使用 firebase use --token 应用到我的脚本中的 OAuth 令牌运行 firebase login:ci 时出现错误消息。 OAuth 令牌是使用拥有我的 Firebase 项目的 Google 用户 ID 生成的。该用户在 Google Cloud IAM 页面(即 https://console.cloud.google.com/iam-admin/iam)上具有“所有者”角色。

当 Google Cloud IAM 页面只允许您设置角色权限时,如何为我的 Google 用户 ID 设置所需的范围 ?

解决方法

我不熟悉 Firebase,但我知道这一点:

  1. Error: Could not load the default credentials

这告诉您没有找到(应用程序)默认凭据。您可以通过执行以下操作使用 Google 用户帐户生成默认凭据:

  1. gcloud auth application-default login

还有其他选择。我写了一个完整的blog post on application default credentials,你可能会觉得有趣。

为了回答你的另一个问题,恐怕我会有点罗嗦...

OAuth

Scopes 是 OAuth 的一个术语;范围并非特定于 GCP 甚至 Google。 OAuth 是一种用于授权的协议,在互联网上得到广泛使用。完全理解 OAuth 并非易事。

OAuth 关注的“各方”是:

  • 资源(您尝试访问的 GCP 服务),
  • 最终用户(你,迈克尔)
  • 授权服务器(Google 帐户服务)和
  • 客户端(在本例中为 firebase CLI;您要代表您执行的程序)。

OAuth 关注的问题如下:作为最终用户,您有权对资源采取行动。您希望客户能够代表您对资源采取行动。为此,您需要使用授权服务器登录,并为客户端获取一个秘密令牌; OAuth 规范中详细定义了如何具体执行此操作。该资源将拥有此类令牌的任何人识别为代表最终用户“发言”。通过将令牌交给客户,您将您的最终用户权限“委托”给了客户。

范围

无论如何...范围从哪里进来?在上述交互中,您不一定要将您在资源上的所有权限委托给客户端。因此,您可以将“范围”绑定到令牌。范围告诉资源,令牌持有者可能不会代表最终用户执行所有操作,而只能执行某些操作。 OAuth 协议没有定义特定范围的含义。范围是自由格式的字符串,它是应该知道如何解释它们的资源。

IAM

另一方面,IAM 定义了最终用户对资源的权限,也就是说,它定义了 Google 帐户在处理 GCP 资源时可以执行的操作。自然,您的 Google 帐户不能将授权委托给它本身没有的客户,即使它可以创建范围非常广泛的令牌。

如果 Google 收到启动 GCE 实例的请求,它会首先检查该请求是否由具有足够范围的有效、可信令牌签名。如果检查通过,Google 会检查“支持”令牌的最终用户是否确实有权使用 IAM 执行请求的操作。

在上面的示例中:您是所有者,因此您拥有大量 IAM 权限。但是,如果您生成的令牌不包含适当的范围,则该令牌不带有该权限,firebase 向 GCP 发送的请求将不会通过第一次检查。

遗产?

范围的概念不是旧的,而是 GCP 使用范围来调节进程权限的方式。

过去,GCP 上的进程通常使用具有非常广泛 (IAM) 权限的通用身份运行,例如默认计算帐户。进程的权限受到为它们生成的令牌的范围限制。

IAM 更强大,可以在更细粒度的级别定义为范围。如今,我们为不同的进程定义具有最小权限的自定义身份。给定适当的 IAM 权限,我们可以简单地创建具有非常广泛范围的令牌,例如 https://www.googleapis.com/auth/cloud-platform

Google App Script/Javascript - 无法使用 Google App Script 循环到 Google 电子表格中的列末尾

Google App Script/Javascript - 无法使用 Google App Script 循环到 Google 电子表格中的列末尾

如何解决Google App Script/Javascript - 无法使用 Google App Script 循环到 Google 电子表格中的列末尾

我正在尝试使用 Google 电子表格抓取 3000 多个数据。我使用 Google App Script 在 A 列中的每个单元格上循环并将其排列在不同的列上。我能够创建一个简单的脚本,该脚本将遍历一个单元格、抓取数据并将其插入到指定的列中。问题是,我制作的脚本直到列末尾都不会抓取或循环。即使我在该列上有 3000 多个数据,它也最多只能抓取该列的 1654 个。数据由个人的多个信息组成。信息由客户的姓名、日期、日期、时间和描述组成。 请注意,列中的 1 个单元格中插入了 1 个数据。这意味着我在 A 列中有 3000 多个带有数据的单元格。

样本数据:

John Doe 星期二,06/21/2021,买了一包泡泡糖

Trish Smith 星期一,06/21/2021,买了一包泡泡糖

Karen Peralta,2021 年 6 月 21 日,星期四,买了一包泡泡糖

附加问题。使用谷歌应用脚​​本循环遍历每个单元格是否有限制?

function rawDataAlteration() {
  var days = new Array(''Monday'',''Tuesday'',''Wednesday'',''Thursday'',''Friday'',''Saturday'',''Sunday'');
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(''Raw Data'');
  var data = spreadsheet.getRange(''A1:A'').getValues();
  var filteredData = new Array();
  for (q in data) {
    if(data[q] != "") {
      filteredData.push(data[q]);
    }
  }
  for (x in filteredData) {
    if (filteredData[x] != "") {
      var convertedToArray = filteredData[x][0].split('','');
      var nametoArray = convertedToArray[0].split('' '');
      var name = new Array();
      var day = "";
      var columnNum = Math.floor(x)+1;
      var nameColumn = ''A''+ columnNum;
      var dayColumn = ''B'' + columnNum;
      var dateColumn = ''C'' + columnNum;
      var shiftColumn = ''D'' + columnNum;
      for(let i in nametoArray){
          let found = false;
          for(let j in days){
              if(nametoArray[i] == days[j]){
                  day = days[j];
                  found = true;
              }
          }
          if(!found){
              name.push(nametoArray[i]);
          }
      }
      var columnB = spreadsheet.getRange(nameColumn).setValue(name.toString().replace('','','' ''));
      var columnD = spreadsheet.getRange(dayColumn).setValue(day);
      var columnD = spreadsheet.getRange(dateColumn).setValue(convertedToArray[1]);
      // Logger.log(filteredData);
    }
  }
}

解决方法

目前,每个脚本执行只能持续 six minutes。如果您的脚本需要更长的时间,它将被中断。

您的代码段显示您在循环中使用了很多 getRange()setValue(),这会导致处理速度变慢,因此不推荐这样做。

根据best practices,更好的方法是批量调用。在您的情况下,这意味着在循环中使用数组处理所有数据,然后在循环外执行 setValues()

关于两步验证杀手锏:Java 接入 Google 身份验证器实战谷歌验证码java的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于Cordova:使用模拟器 x86 (google play) 不适用于 x86 google apis 和 x86_64 google apis、GAS:将来自 Google Drive 中多个 Google Sheets 文档工作簿的数据合并到一个工作簿中 获取特定列:移动文件:如何在 Google 云端硬盘中移动文件、Google API 的 Google OAuth 2.0 范围与 Google Cloud 上的 IAM 中的角色和权限有何不同? OAuth范围IAM遗产?、Google App Script/Javascript - 无法使用 Google App Script 循环到 Google 电子表格中的列末尾等相关内容,可以在本站寻找。

本文标签: