Spring Boot 使用Sping Boot 的密钥隐藏密钥隐藏SecurityContext始终为空

bvjxkvbb  于 2023-03-08  发布在  Spring
关注(0)|答案(2)|浏览(215)

我试着使用Keycloak与 Spring 启动,但我面临的问题。身份验证与适配器工作正常,但不是授权。
这是我的配置:

keycloak.realm = master
keycloak.auth-server-url = http://127.0.0.1:8080/auth
keycloak.ssl-required = none
keycloak.resource = pactng
keycloak.credentials.secret = **************************
keycloak.use-resource-role-mappings = true
keycloak.principal-attribute=preferred_username
keycloak.bearer-only = true

keycloak.policy-enforcer-config.userManagedAccess=org.keycloak.representations.adapters.config.PolicyEnforcerConfig.UmaProtocolConfig
keycloak.policy-enforcer-config.lazyLoadPaths=true

keycloak.policy-enforcer-config.paths[0].path=/*
keycloak.policy-enforcer-config.paths[0].methods[0].method=GET
keycloak.policy-enforcer-config.paths[0].methods[0].scopes[0]=urn:pactng:scopes:read
keycloak.policy-enforcer-config.paths[0].methods[1].method=POST
keycloak.policy-enforcer-config.paths[0].methods[1].scopes[0]=urn:pactng:scopes:create
keycloak.policy-enforcer-config.paths[0].methods[2].method=PUT
keycloak.policy-enforcer-config.paths[0].methods[2].scopes[0]=urn:pactng:scopes:update
keycloak.policy-enforcer-config.paths[0].methods[3].method=PATCH
keycloak.policy-enforcer-config.paths[0].methods[3].scopes[0]=urn:pactng:scopes:update
keycloak.policy-enforcer-config.paths[0].methods[4].method=DELETE
keycloak.policy-enforcer-config.paths[0].methods[4].scopes[0]=urn:pactng:scopes:delete

我在这里没有定义角色,我希望适配器根据访问令牌中包含的请求和权限动态计算授权。
这是我的KeycloakConfig用于 Spring 安全:

@KeycloakConfiguration
public class KeycloakConfig extends KeycloakWebSecurityConfigurerAdapter {

    /**
     * Map keycloak role to spring ROLE_<ROLE>
     * @param auth
     */
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) {
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

    /**
     * Defined the strategy use by keycloak for user session. We need authorization system so we use a session for a confidential client.
     * Can be NullAuthenticatedSessionStrategy for bearerClient
     * @return
     */
    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }

    /**
     * Use spring boot application.properties instead of keycloak.json to retrieve
     * connexion informations
     */
    @Bean
    public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.csrf().disable()
                .authorizeRequests()
                .antMatchers("/api/*").authenticated()
                .anyRequest().permitAll();
    }
}

我通过以下请求检索令牌进行测试。UMA 2被激活,因为它似乎不可能在没有它的情况下使用此适配器启用授权。

# Get Access Token for a user.
POST http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/token
{
    client_id   "<CLIENT_ID>"
    client_secret   "<CLIENT_SECRET>"
    username    "<USERNAME>"
    password    "<USER_PASSWORD>"
    grant_type  "password"
}

这给了我一个访问令牌,我在下面的请求中使用。

# Try to get access to the resource endpoint
GET http://localhost:8081/api/v1/<resources>
Headers: authorization: Bearer <ACCESS_TOKEN>

这给了我一个401 WWW认证,遵循UMA2规范,并带有一个票证。然后我联系keycloak以获得一个RPT:

# Get RPT from Keycloak
POST http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/token
Headers: authorization: Bearer <ACCESS_TOKEN>
{
    grant_type: "urn:ietf:params:oauth:grant-type:uma-ticket"
    ticket: <TICKET>
}

Keycloak给了我一个RPT,这是一个包含权限的访问令牌。然后我用这个RPT重试获取资源

# Try to get access to the resource endpoint
GET http://localhost:8081/api/v1/<resources>
Headers: authorization: Bearer <RPT>

但是,适配器没有访问资源,而是再次给我一个401 WWW身份验证。
我深入研究了代码,发现在AbstractPolicyEnforcer中KeycloakSecurityContext始终为空:

public AuthorizationContext authorize(OIDCHttpFacade httpFacade) {
        EnforcementMode enforcementMode = getEnforcerConfig().getEnforcementMode();
        // Always return null
        KeycloakSecurityContext securityContext = httpFacade.getSecurityContext();

这使得代码每次都被困在这部分代码中:

if (securityContext == null) {
     if (!isDefaultAccessDeniedUri(request)) {
          if (pathConfig != null) {
               if (EnforcementMode.DISABLED.equals(pathConfig.getEnforcementMode())) {
                   return createEmptyAuthorizationContext(true);
               } else {
                   challenge(pathConfig, getRequiredScopes(pathConfig, request), httpFacade);
               }
           } else {
                    handleAccessDenied(httpFacade);
           }
      }
      return createEmptyAuthorizationContext(false);
 }

所以我的问题是,在这个长时间的解释之后,为什么这个securityContext没有被填充?我错过了什么吗?

c9x0cxw0

c9x0cxw01#

好的,我找到了解决方案。看起来这个适配器需要一个角色上的securityConstraints来完成它的工作。所以我添加了这个来使它工作:

keycloak.securityConstraints[0].authRoles[0]=*
keycloak.securityConstraints[0].securityCollections[0].patterns[0]=/*

这基本上告诉它处理所有路径上所有角色。
请继续使用JAVA11,因为它与最新的JDK版本不兼容.

5cg8jx4n

5cg8jx4n2#

@斯堪的纳维亚我补充更多关于您的答案的细节:必须在Bean默认init KeycloakSecurityContext的spirng-profile中使用“keycloak”前缀配置代理实施器。之后,如果要覆盖多领域设置的KeycloakResolverConfig,只需根据从http请求标头发送的“客户端领域”使用实施器配置初始化KeycloakDeployment对象,并替换为剩余的现有Keycloak部署:

class Xxx implements KeycloakConfigResolver {
    @Override
    public KeycloakDeployment resolve(HttpFacade.Request request) {
        String realm = request.getHeader(KEY);
        KeycloakDeployment deployment = cache.get(realm); // cache is inmemory cache...
        if (null == deployment) {
            var config = getConf(realm); // init at bootstrap all objects copy look like KeycloakSpringBootProperties class but prefix yaml by 'realm' name
            if (config == null) throw new SecurityException(String.format("PolicyEnforcer for realm %s is null", realm));
            // Create new KeycloakDeployment from AdapterConfig
            deployment = KeycloakDeploymentBuilder.build(config);
            cache.put(realm, deployment);
        }
        return deployment;
    }

}

在您的yaml:

## Default for init KeycloakSecurityContext
keycloak:
  policy-enforcer-config:
    enforcement-mode: ENFORCING
    lazy-load-paths: true
    paths:
      - path: "/api/shipping/docs/*"
        enforcement-mode: DISABLED
      - path: "/api/shipping/outbound/*"
        enforcement-mode: DISABLED
      - path: "/api/shipping/internal/*"
        enforcement-mode: ENFORCING
  securityConstraints:
    - authRoles: '*'
      securityCollections:
        - patterns:
            - /api/shipping/test/*
            - /api/shipping/internal/*
  auth-server-url: https://your.keycoak.vn
  realm: master
  bearer-only: 'true'
  use-resource-role-mappings: false
  ssl-required: external
  resource: internal-vn
  credentials:
    secret: xxx

## Prefix KeycloakDeployment 1
external-policy:
  policy-enforcer-config:
    enforcement-mode: ENFORCING # ENFORCING, PERMISSIVE, DISABLED
    paths:
      - path: "/error"
        enforcement-mode: DISABLED
      - path: "/api/shipping/docs/*"
        enforcement-mode: DISABLED
      - path: "/api/shipping/outbound/*"
        enforcement-mode: DISABLED
      - path: "/api/shipping/internal/*"
        enforcement-mode: ENFORCING
      - path: "/api/shipping/test/testing-role"
        enforcement-mode: ENFORCING
  securityConstraints:
    - authRoles: "*"
      securityCollections:
        - patterns:
            - "/*"
  auth-server-url: https://your.keycoak.vn
  realm: ctv-vn
  bearer-only: 'true'
  use-resource-role-mappings: true
  ssl-required: external
  resource: customer-service
  credentials:
    secret: xxx

## Prefix KeycloakDeployment 2
internal-policy:
  policy-enforcer-config:
    enforcement-mode: ENFORCING
    lazy-load-paths: true
    paths:
      - path: "/api/shipping/docs/*"
        enforcement-mode: DISABLED
      - path: "/api/shipping/outbound/*"
        enforcement-mode: DISABLED
      - path: "/api/shipping/internal/*"
        enforcement-mode: PERMISSIVE
  securityConstraints:
    - authRoles: '*'
      securityCollections:
        - patterns:
            - /api/shipping/test/*
            - /api/shipping/internal/*
  auth-server-url: https://your.keycoak.vn
  realm: master
  bearer-only: 'true'
  use-resource-role-mappings: false
  ssl-required: external
  resource: internal-vn
  credentials:
    secret: xxx

相关问题