我正在尝试使用自定义REST端点制作自定义SPI,该端点应通过评估对请求资源的权限来对传入请求进行身份验证和授权。 在调试器的帮助下,我发现我应该在REST处理程序方法中使用TokenEndpoint.java类并调用方法PermissionGrant(),但是当我尝试创建TokenEndpoint实例时,出现REASTEASY错误和Keycloak崩溃。 你有什么例子,我该怎么办?
答案 0 :(得分:1)
我建议看一下以下项目:keycloak-avatar-minio-extension。
首先,您必须实现RealmResourceProdiverFactor和RealmResourceProdiver。
第二,您需要触发RealmResourceProvider中的getResource()时返回的资源。
您的资源是一个用于定义端点的类。 要检查授权,您可以创建如下方法:
private AuthenticationManager.AuthResult resolveAuthentication(KeycloakSession session) {
AppAuthManager appAuthManager = new AppAuthManager();
RealmModel realm = session.getContext().getRealm();
AuthenticationManager.AuthResult authResult = appAuthManager.authenticateIdentityCookie(session, realm);
if (authResult != null) {
return authResult;
}
return null;
}
此方法在构造函数中调用,并在Resource中设置private final AuthenticationManager.AuthResult auth;
变量。
现在,在端点实现中,您可以简单地检查auth
是否不为null,或者,如果需要,可以执行更复杂的操作,例如检查auth
变量中可用的用户或令牌。
答案 1 :(得分:1)
和其他人一样,我需要在我们放入 keycloak 实例的自定义 rest 端点中使用它。
我分步骤解决了这个问题:
代码如下:
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.ws.rs.GET;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.common.DefaultEvaluationContext;
import org.keycloak.authorization.common.UserModelIdentity;
import org.keycloak.authorization.model.Resource;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.permission.ResourcePermission;
import org.keycloak.authorization.permission.evaluator.Evaluators;
import org.keycloak.authorization.permission.evaluator.PermissionEvaluator;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.authorization.AuthorizationRequest;
import org.keycloak.representations.idm.authorization.Permission;
import org.keycloak.services.managers.AppAuthManager;
import org.keycloak.services.managers.AuthenticationManager.AuthResult;
public class DemoResource {
private final KeycloakSession session;
private final AuthResult auth;
public DemoResource(KeycloakSession session) {
this.session = session;
this.auth = new AppAuthManager.BearerTokenAuthenticator(session).authenticate();
}
@GET
@Path("/demoresources")
@Produces(MediaType.APPLICATION_JSON)
public Set<Resource> listDemoResources() {
if (this.auth == null || this.auth.getToken() == null) {
throw new NotAuthorizedException("Bearer");
}
String clientId = ""; // Client id which resources are defined.
String resourceType = ""; // Get resources by type.
final RealmModel realm = this.session.getContext().getRealm();
final AuthorizationProvider authorizationProvider = this.session.getProvider(AuthorizationProvider.class);
final ClientModel client = this.session.clientStorageManager().getClientByClientId(realm, clientId);
final ResourceServer resourceServer = authorizationProvider
.getStoreFactory()
.getResourceServerStore()
.findById(client.getId());
final Evaluators evaluators = authorizationProvider.evaluators();
final AuthorizationRequest request = new AuthorizationRequest();
request.setSubjectToken(this.auth.getToken().toString());
// Get resources by type and put them in a map
final Map<String, Resource> resourceMap = authorizationProvider
.getStoreFactory()
.getResourceStore()
.findByType(resourceType, resourceServer.getId())
.stream()
.collect(Collectors.toMap(Resource::getId, r -> r));
// Generate a permission evaluator for all resources of given type
final PermissionEvaluator permissionEvaluator = evaluators
.from(
resourceMap
.entrySet()
.stream()
.map(r -> new ResourcePermission(r.getValue(), Collections.emptyList(), resourceServer))
.collect(Collectors.toList()),
new DefaultEvaluationContext(new UserModelIdentity(realm, this.auth.getUser()), this.session));
// Evaluate permission and put them in a result set.
final Collection<Permission> permissions = permissionEvaluator.evaluate(resourceServer, request);
final Set<Resource> resources = new HashSet<>();
for (final Permission permission : permissions) {
if (resourceMap.containsKey(permission.getResourceId())) {
resources.add(resourceMap.get(permission.getResourceId()));
}
}
return resources;
}
}
供应商
import org.keycloak.models.KeycloakSession;
import org.keycloak.services.resource.RealmResourceProvider;
public class DemoProvider implements RealmResourceProvider {
private KeycloakSession session;
public DemoProvider(KeycloakSession session) {
this.session = session;
}
@Override
public void close() {
}
@Override
public Object getResource() {
return new DemoResource(this.session);
}
}
提供者工厂
import org.keycloak.Config.Scope;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.services.resource.RealmResourceProvider;
import org.keycloak.services.resource.RealmResourceProviderFactory;
public class DemoProviderFactory implements RealmResourceProviderFactory {
public static final String ID = "demo";
@Override
public RealmResourceProvider create(KeycloakSession session) {
return new DemoProvider(session);
}
@Override
public void init(Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public void close() {
}
@Override
public String getId() {
return ID;
}
}
答案 2 :(得分:0)
尝试从文档中查看这些Java示例。 https://www.keycloak.org/docs/latest/authorization_services/index.html#_authorization_quickstarts
答案 3 :(得分:0)
我最近遇到了同样的问题。通常,Val的答案是正确的。 为了使他的代码正常工作,我们必须向keycloak-services模块添加依赖项。您既需要编译时依赖(不要将jar添加到ear libs中)又需要模块依赖。 https://github.com/dteleguin/beercloak
是一个很好的例子景点:
在新版本中,身份验证在构造函数中不起作用,必须使用GET STACKED DIAGNOSTICS
方法来完成。