当前位置: 首页 > 知识库问答 >
问题:

机密的Rest-Api带权限-总是403s-我做错了什么?

贝阳泽
2023-03-14

我已经试了好几个小时了,似乎遇到了麻烦。如有任何建议/帮助,将不胜感激。

目标:我想授权express rest api(前客户端id:“我的rest api”)跨映射到客户端范围的各种HTTP方法(示例:“创建”/“读取”/“更新”/“删除”)路由(示例资源:“WeatherForecast”)。我想通过策略控制这些权限(例如,如果满足策略“仅管理组”(用户属于管理组),则将授予“Read-WeatherForecast-Permission”。

Rest api不会让用户登录(将从前端直接与Keyclope对话,然后他们将使用该令牌与Rest api对话)。

环境:

  • Keyclope 15.1.1在docker上的自己的容器(端口8080)中本地运行(与rest api共享网络)

发生了什么:我可以通过postman从keycloak登录页面登录并获取访问令牌。但是,当我点击任何使用keycloak.protect()或keycloak.enforce()的endpoint(无论是否指定资源权限)时,我都无法通过。在以下代码中,删除endpoint返回200 postman中keycloak登录页面的超文本标记语言,获取返回403“访问拒绝”。

目前的境界

  • 测试用户(我在Postman中与他一起登录)有组“Admin”

Nodejs代码的当前状态:

import express from 'express';
import bodyParser from 'body-parser';
import session from "express-session";
import KeycloakConnect from 'keycloak-connect';

const app = express();

app.use(bodyParser.json());

const memoryStore = new session.MemoryStore();
app.use(session({
    secret: 'some secret',
    resave: false,
    saveUninitialized: true,
    store: memoryStore
  }));

const kcConfig: any = { 
    clientId: 'my-rest-api',
    bearerOnly: true,
    serverUrl: 'http://localhost:8080/auth',
    realm: 'my-realm',
};
const keycloak = new KeycloakConnect({ store: memoryStore }, kcConfig);

app.use(keycloak.middleware({
    logout: '/logout',
    admin: '/',
}));

app.get('/api/WeatherForecast', keycloak.enforcer(['WeatherForecast:read'],{  resource_server_id: "my-rest-api"}), function (req, res) {
   res.json("GET worked")
  });

app.delete('/api/WeatherForecast', keycloak.protect(), function (req, res) {
     res.json("DELETE worked")
});

app.listen(8081, () => {
    console.log(`server running on port 8081`);
  });
  

尝试了其他一些方法:

  • 我尝试使用从postman获得的令牌调用带有curl的RPTendpoint,并且RPT令牌非常好,看到了预期的权限。
  • 我尝试调用keycloak.check权限({权限:[{id:"Weather预测",作用域:["读取"]}]}, req)。

我真的很想使用keydropage,我觉得我的团队很快就能做到这一点,但需要一些帮助才能通过这一部分。非常感谢。

-------------------结束原始问题------------------------

编辑/更新#1:好吧,所以又花了几个小时。决定阅读它点击和调试的每一行keycloak-connect库。在检查权限的最后一行发现它在keycloak-connect/middleware/auth-utils/grant-manager.js内失败。没有显示错误或捕获块来调试-进一步追踪兔子洞我能够发现它发生在使用超文本传输协议选项的fetch方法中:

'{"protocol":"http:","slashes":true,"auth":null,"host":"localhost:8080","port":"8080","hostname":"localhost","hash":null,"search":null,"query":null,"pathname":"/auth/realms/my-realm/protocol/openid-connect/token","path":"/auth/realms/my-realm/protocol/openid-connect/token","href":"http://localhost:8080/auth/realms/my-realm/protocol/openid-connect/token","headers":{"Content-Type":"application/x-www-form-urlencoded","X-Client":"keycloak-nodejs-connect","Authorization":"Basic YW(etc...)Z2dP","Content-Length":1498},"method":"POST"}'

它似乎没有进入该fetch/http包装器的回调。我在启动命令中添加了NODE\u DEBUG=http,并找到了吞没的错误,看起来我回到了起点:

HTTP 31: SOCKET ERROR: connect ECONNREFUSED 127.0.0.1:8080 Error: connect ECONNREFUSED 127.0.0.1:8080

    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1157:16)

    at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17)

然后我看到了一些我认为可能与我的docker网络设置有关的东西(dockerize环境中的Keycloak和Spring Boot Web应用程序),并尝试更改主机名dns,以便我可以使用其他本地主机,但它也不起作用(甚至添加到重定向uri等)。

更新#2:好吧,我拿到了钥匙斗篷。protect()(纯身份验证)终结点现在正在工作。我通过阅读keybove connect lib代码发现了更多选项,似乎在实例化keybove connect时向keybove config对象添加“realmPublicKey”修复了这个问题。授权密钥斗篷仍然没有成功。强制一侧。

const kcConfig: any = { 
    clientId: 'my-rest-api',
    bearerOnly: true,
    serverUrl: 'http://localhost:8080/auth',
    realm: 'my-realm',
    realmPublicKey : "MIIBIjANBgk (...etc) uQIDAQAB",
};

共有1个答案

朱梓
2023-03-14

因此,我的团队最终找到了答案——解决方案分为两部分:

  1. 遵循类似问题的说明stackoverflow问题答案,例如:https://stackoverflow.com/a/51878212/5117487如果链接以某种方式断开,请采取粗略的步骤:
  • 为127.0.0.1keycloak添加主机条目(如果'keycloak'是keycloak的docker容器的名称,我更改了docker-compose以指定容器名称以使其更安全)
  • 将keycloak-connect config AuthServerUrl设置为:'超文本传输协议://keycloak: 8080/auth/'而不是'http://localhost:8080/auth/'
  • “”http://localhost:8080/auth/realms/abra/protocol/openid-连接/验证“-
 类似资料:
  • 它返回几个错误,其中大多数显示:<代码> 我对编码很陌生,我只是想用推特API制作一个有趣的机器人,但有很多错误,我不知道该怎么办。 出现的主要错误如下: (从集合导入namedtuple,映射导入错误:无法从“集合”导入名称“映射”) 谁能帮帮我吗? 出现的错误:回溯(最近一次调用):文件“C:\Users\wgama\PycharmProjects\botesquilo\botesquilo.

  • 我正在做一个项目,我的意图是运行一个玉米作业,并发送邮件给我的朋友,祝他们生日,我能够从MySQL DB获取电子邮件,并将其与当前日期进行比较,但当涉及到发送电子邮件时,我得到NullPointerException。 我确信应用程序属性没有问题,我在其他项目中也使用了它们,它们的功能正常 这是我得到以下信息的错误

  • 11:15:57创建表如果不存在tblcompany(companyid INT(11)无符号NOT NULL,custfirst VARCHAR(50),custlast VARCHAR(50),company VARCHAR(50),custphone VARCHAR(50), custemail VARCHAR(50),主键(companyid),索引(companyid),约束外键(com

  • 我和赫尔姆一起在GKE上安装库伯内特斯外部秘密。 GKE: 1.16.15-gke.6000 on Asia-northeast1 舵手应用6.2.0版本 使用工作负载标识作为文档写入 对于工作负载标识,我绑定为下面命令的服务号(my-intices-sa@$PROJECT.iam.gserviceaccount.com)具有秘书anager.admin角色,这对于使用谷歌秘密管理器似乎是必要的

  • 问题内容: 我有一些代码来计算圆的属性: 它计算周长,但不计算其余部分。 问题答案: 是一个,也一个,这意味着不能在第二个打印语句中使用。试试那里。 回想一下,这是浮点数,而整数。在的文档中对此进行了概述(请参阅“ 格式化字符串语法”)。

  • 我正在使用EclipseIDE编程。在完成有关Apache POI的教程后: https://www.youtube.com/watch?v=RsrF2Ku7ad4 我通过eclipse和以下链接创建了一个可执行jar:http://help.eclipse.org/mars/index.jsp?topic=/org.eclipse.jdt.doc.user/tasks/tasks-37.htm