Cloud Run + Cloud Endpoints +服务帐户身份验证–在curl中有效,但在JS中使用访存API时无效

如何解决Cloud Run + Cloud Endpoints +服务帐户身份验证–在curl中有效,但在JS中使用访存API时无效

我已经配置了执行GCF的云端点。当云运行服务允许allUsers调用API时,一切正常。

一旦我删除allUsers并使用服务帐户进行身份验证,云运行控制台中将显示403错误:

请求未通过验证。允许未经身份验证的调用或设置适当的Authorization标头。在https://cloud.google.com/run/docs/securing/authenticating

中了解更多信息

Chrome JS控制台显示以下错误消息:

可从原始位置访问“ https://.run.app/do-this&key=” “ http://0.0.0.0:8080”已被CORS政策阻止:未响应预检请求 通过访问控制检查:请求中不存在“ Access-Control-Allow-Origin”标头 资源。如果不透明的响应满足您的需求,请将请求的模式设置为“ no-cors”以获取 禁用了CORS的资源。

这是我在浏览器中运行的JS代码:

        let options: RequestInit = {
            headers: {
                'Authorization': `Bearer ${token}`,},}
        
        const result = await fetch(fetchURL,options);

使用相同令牌运行curl时,我得到了预期的响应

curl -H "Authorization: Bearer ${token}" 'https://<my-api>.run.app/do-this&key=<key>'

出于完整性考虑,这里也是端点yaml

swagger: '2.0'
info:
  title: My first widget
  description: This is a great widget
  version: 1.0.0
host: <my-api>.run.app
schemes:
  - https
produces: 
  - application/json
paths:
  /do-this:
    get:
      summary: Do-this
      operationId: doit
      x-google-backend:
        address: https://<project-id>.cloudfunctions.net/do-that
      responses:
        '200':
          description: A successful response.
          schema:
            type: string
        '403':
          description: An error occurred
          schema:
            type: string
      security:
        - api_key: []

securityDefinitions:
  # This section configures basic authentication with an API key.
  api_key:
    type: "apiKey"
    name: "key"
    in: "query"

更新esp的命令:

gcloud run services update <my-api> --set-env-vars="^|^ENDPOINTS_SERVICE_NAME=<my-api>.run.app|ESP_ARGS=--rollout_strategy=managed,--cors_preset=basic" --project=<project-id> --platform=managed --region=europe-west1

更新

启用cors浏览器端无济于事。

Google文档提到应该call from outside GCP

如果您要从无法访问计算元数据的计算实例(例如您自己的服务器)调用服务,则必须手动生成适当的令牌:
使用target_audience声明设置为接收服务URL的服务帐户JWT自签名。 将自签名的JWT交换为Google签名的ID令牌,该令牌应将aud声明设置为上述URL。 将ID令牌包括在对服务的请求中的Authorization:Bearer ID_TOKEN标头中。 尽管Cloud Run(完全托管)尚不支持身份识别代理,但是您可以检查身份识别代理示例代码,以获取上述步骤的代码示例。

The end-users section:尽管提及CORS

构建Web应用程序时,必须解决跨域资源共享(CORS)问题。例如,发送的CORS预检请求没有Authorization标头,因此它们在非公共服务上被拒绝。因为预检请求失败,所以主请求也将失败。
要解决此问题,您可以将您的Web应用程序和服务托管在同一域中,以避免CORS的预检请求。您可以使用Firebase托管来实现。

我尝试在Firebase托管上托管JS脚本和HTML,但问题仍然存在。

想到的另一个问题是:我是否需要在开放api规范中同时设置OAuth和API密钥身份验证?

更新2

This discussion建议无法将Cloud Run与支持CORS的身份验证一起使用。我还想知道为什么会卷曲。我正在使用服务帐户令牌进行身份验证,而不是最终用户。

解决方法

未为Cloud Endpoint激活cors。像这样更新您的openAPI规范

IloCplex mycplex = new IloCplex();

int Ncd=2;
int Nbv=6;
int T=4;

IloNumVar[][][][] y = new IloIntVar[Ncd][][][];
        for(int i=0; i<y.length;i++) {
            y[i]= new IloIntVar[Ncd][][];
            for(int j=0; j<y[i].length;j++) {
                y[i][j]= new IloIntVar[Nbv+1][];
                for(int k=1; k<y[i][j].length; k++) {
                    

                        y[i][j][k]= mycplex.boolVarArray(T+1);
for(int t=1; t<T; t++)
{
                        IloRange myConstraint2 = mycplex.addEq(y[i][j][k][t],1);
mycplex.add(myConstraint2);
}


            }
        }
    }

mycplex.solve();


for (int i = 0; i < Ncd; i++) {

                for (int j = 0; j < Ncd; j++) {
                   for (int k = 1; k < Nbv; k++) {
                           for(int t=1; t<T; t++)
                      System.out.printf("valeur = "+mycplex.getValue(y[i][j][k][t]));
                      }
                   }
                } 

或按照错误消息的说明设置swagger: '2.0' info: title: My first widget description: This is a great widget version: 1.0.0 host: <my-api>.run.app x-google-endpoints: - name: <my-api>.run.app allowCors: True ... ... ... 来签入您的电话。

,

我通过以下方式使其工作:

  1. oauth作为安全性定义添加到OpenAPI规范中,并将其与每个API路径的api密钥一起使用
  2. 使用--set-env-vars="^|^ENDPOINTS_SERVICE_NAME=<my-api>.run.app|ESP_ARGS=--cors_preset=basic,--rollout_strategy=managed"部署端点
  3. 在Cloud Function中,将Access-Control-Allow-Origin设置为空字符串''res.setHeader("Access-Control-Allow-Origin",'')
  4. 允许allUsers可以访问Cloud Run容器

每个人都可以访问Cloud Run容器时,端点将负责身份验证。

令我惊讶的是,CF自动在mydomain.com标头中添加了呼叫主机(例如*)和Access-Control-Allow-Origin。此标头中不允许使用多个项目,因此我放弃了mydomain.com并保留了*

我将尝试使用不同的选项,完成后将提供所有步骤的操作方法。任何意见/建议都非常感谢!

更新

深入研究之后,我了解到Access-Control-Allow-Origin会自动添加const cors = require('cors')({origin: true});

对于我的用例,我不需要CF内的cors,因为只能从Cloud Run ESP中访问它们。

因此重要的步骤是:

  • 将oauth添加到OpenAPI规范
  • 通过ESP_ARGS启用cors
  • 允许allUsers可以访问云运行容器

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-