4.6. 保护资源
- 简单身份验证
-
要强制在访问资源前必须验证用户,只需使用 no-argument 版本
keycloak.protect ():
app.get( '/complain', keycloak.protect(), complaintHandler );
app.get( '/complain', keycloak.protect(), complaintHandler );
- 基于角色的授权
- 使用当前应用程序的 application 角色保护资源:
app.get( '/special', keycloak.protect('special'), specialHandler );
app.get( '/special', keycloak.protect('special'), specialHandler );
使用不同应用程序的应用程序角色 保护资源 :
app.get( '/extra-special', keycloak.protect('other-app:special'), extraSpecialHandler );
app.get( '/extra-special', keycloak.protect('other-app:special'), extraSpecialHandler );
使用 realm 角色保护资源:
app.get( '/admin', keycloak.protect( 'realm:admin' ), adminHandler );
app.get( '/admin', keycloak.protect( 'realm:admin' ), adminHandler );
- 基于资源的授权
-
基于资源的授权允许您根据 Keycloak 中定义的一组策略来保护资源及其特定方法/操作,从而外部化来自应用程序的授权。这可以通过公开一个
keycloak.enforcer方法来实现,您可以使用它来保护资源 ClusterClaim
app.get('/apis/me', keycloak.enforcer('user:profile'), userProfileHandler);
app.get('/apis/me', keycloak.enforcer('user:profile'), userProfileHandler);
keycloak-enforcer 方法以两种模式运行,具体取决于 response_mode 配置选项的值。
app.get('/apis/me', keycloak.enforcer('user:profile', {response_mode: 'token'}), userProfileHandler);
app.get('/apis/me', keycloak.enforcer('user:profile', {response_mode: 'token'}), userProfileHandler);
如果将 response_mode 设为 token,则代表发送到应用程序的 bearer 令牌从服务器获取权限。在这种情况下,Keycloak 签发一个新的访问令牌,并带有服务器授予的权限。如果服务器没有以预期权限响应令牌,则请求将被拒绝。使用此模式时,您应该可以从请求获取令牌,如下所示:
当应用程序使用会话时,且您想要缓存来自服务器的以前的决策,并自动处理刷新令牌,首选这个模式。此模式对于充当客户端和资源服务器的应用特别有用。
如果将 response_mode 设为 permissions (默认模式),服务器仅返回授予权限的列表,而不发出新的访问令牌。除了不发布新令牌外,此方法还通过 请求 公开服务器授予权限,如下所示:
app.get('/apis/me', keycloak.enforcer('user:profile', {response_mode: 'permissions'}), function (req, res) {
const permissions = req.permissions;
// show user profile
});
app.get('/apis/me', keycloak.enforcer('user:profile', {response_mode: 'permissions'}), function (req, res) {
const permissions = req.permissions;
// show user profile
});
无论使用的 response_mode 是什么,keycloak.enforcer 方法首先会尝试检查发送到应用程序的 bearer 令牌中的权限。如果 bearer 令牌已执行预期权限,则不需要与服务器交互来获取决策。当您的客户端能够在访问受保护的资源之前从具有预期权限的服务器获取访问令牌时,这特别有用,因此他们可以使用 Keycloak 授权服务(如增量授权)提供的一些功能,并在 keycloak.enforcer 强制访问资源时,避免对服务器进行额外的请求。
默认情况下,策略强制器将使用定义为应用程序的 client_id (例如,通过 keycloak.json)来引用支持 Keycloak 授权服务中的客户端。在这种情况下,客户端不能是公共的,它实际上是一个资源服务器。
如果您的应用程序充当公共客户端(frontend)和资源服务器(backend),您可以使用以下配置使用您要强制的策略在 Keycloak 中引用不同的客户端:
keycloak.enforcer('user:profile', {resource_server_id: 'my-apiserver'})
keycloak.enforcer('user:profile', {resource_server_id: 'my-apiserver'})
建议您在 Keycloak 中使用不同的客户端来代表您的前端和后端。
如果您要使用 Keycloak 授权服务启用了保护的应用程序,且已在 keycloak.json 中定义了客户端凭证,您可以将额外的声明推送到服务器,并将其提供给您的策略,以便做出决策。为此,您可以定义一个 claims 配置选项,它需要一个会返回一个带有您要推送的声明的 JSON 的函数:
有关如何将 Keycloak 配置为保护您的应用程序资源的更多详细信息,请参阅 授权服务指南。
- 高级授权
- 要保护基于 URL 本身的部分的资源,假设每个部分都存在角色:
function protectBySection(token, request) {
return token.hasRole( request.params.section );
}
app.get( '/:section/:page', keycloak.protect( protectBySection ), sectionHandler );
function protectBySection(token, request) {
return token.hasRole( request.params.section );
}
app.get( '/:section/:page', keycloak.protect( protectBySection ), sectionHandler );
高级登录配置:
默认情况下,所有未授权的请求都会被重定向到红帽构建的 Keycloak 登录页面,除非您的客户端是 bearer-only。但是,机密或公共客户端可以同时托管可浏览和 API 端点。要防止未经身份验证的 API 请求重定向并返回 HTTP 401,您可以覆盖 redirectToLogin 功能。
例如,此覆盖会检查 URL 是否包含 /api/ 并禁用登录重定向:
Keycloak.prototype.redirectToLogin = function(req) {
const apiReqMatcher = /\/api\//i;
return !apiReqMatcher.test(req.originalUrl || req.url);
};
Keycloak.prototype.redirectToLogin = function(req) {
const apiReqMatcher = /\/api\//i;
return !apiReqMatcher.test(req.originalUrl || req.url);
};