将 Swagger-ui 用于受密钥斗篷保护的应用程序

Use Swagger-ui for a keycloak protected App

我正在尝试通过 spring-boot 和 keycloak-admin-client 建立一个用户服务来访问 keycloak。

edit:我应该提到 运行 服务和 keycloak 在不同的 docker 容器中,我认为这可能是问题所在。 我的 AUTH_SERVER 设置为 keycloak:8080,我让它重定向到我的主机文件中的本地主机。

edit2: 我设法通过 swagger 获得了令牌,但是用户创建仍然以 403 Forbidden 结束,尽管如果 运行招摇之外。我的 spring-boot 或我的招摇似乎有问题。 很巧的是,我能顺利拿到令牌。

我想创建一个用户并提供一个登录端点,另一个服务可以使用 username/password 登录用户并取回令牌。

如果我在 main 方法中 运行 在 swagger 之外创建用户的代码有效,并且我可以通过邮递员获得令牌。 (现在也通过招摇) 但是使用 swagger-ui,我在尝试创建用户时收到“403 Forbidden”。

我已经通过 resttemplate 和 keycloak 的 admin-cli 尝试了 Postrequest。 两者都在 运行 时独立于 swagger 工作,并且都不适用于 swagger。

  @PostMapping(path = "new")
  public ResponseEntity<String> addUser(UserData userData) {
    UserRepresentation user = new UserRepresentation();
    user.setEnabled(true);
    user.setUsername(userData.getUsername());
    user.setFirstName(userData.getFirstName());
    user.setLastName(userData.getLastName());
    RealmResource realmResource = getRealmResource();
    UsersResource userResource = realmResource.users();
    Response response = userResource.create(user);
    log.info("Response: " + response.getStatusInfo());
    return new ResponseEntity<>("User created with userId: " + userData.getBusinessEntityId(),
      HttpStatus.OK);
  }

我的安全配置:


  /*
   Submits the KeycloakAuthenticationProvider to the AuthenticationManager
   */
  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
    keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
    auth.authenticationProvider(keycloakAuthenticationProvider);
  }

  @Bean
  public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
    return new KeycloakSpringBootConfigResolver();
  }

  @Bean
  @Override
  protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
    return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);
    http.authorizeRequests()
      .antMatchers("/api/v1/user/admin").hasRole("admin")
      .antMatchers("/api/v1/user/vendor").hasRole("vendor")
//      .antMatchers("/api/v1/user/customer").hasRole("customer")
      .anyRequest().permitAll();
  }

我的 Swagger 配置:


    @Bean
  public Docket apiDocumentation() {
    return new Docket(DocumentationType.SWAGGER_2)
      .select()
      .apis(RequestHandlerSelectors.any())
      .paths(PathSelectors.any())
      .build()
      .securitySchemes(Arrays.asList(securityScheme()))
      .securityContexts(Arrays.asList(securityContext()));
  }

  private SecurityScheme securityScheme() {
    return new OAuthBuilder()
      .name("spring_oauth")
      .grantTypes(grantTypes())
      .build();
  }

  private SecurityContext securityContext() {
    return SecurityContext.builder()
      .securityReferences(Arrays.asList(new SecurityReference("spring_oauth", new AuthorizationScope[]{})))
      .forPaths(PathSelectors.any())
      .build();
  }

  private List<GrantType> grantTypes() {
    GrantType grantType = new ClientCredentialsGrant(AUTH_SERVER + "/realms/User-Service-Realm/protocol/openid-connect/token");
    return Arrays.asList(grantType);
  }

  @Bean
  public SecurityConfiguration security() {
    return SecurityConfigurationBuilder.builder()
      .realm(REALM)
      .clientId(CLIENT_ID)
      .clientSecret(CLIENT_SECRET)
      .scopeSeparator(" ")
      .useBasicAuthenticationWithAccessCodeGrant(true)
      .build();
  }

我的 Keycloak 设置:

我可以管理它在客户凭证授予中工作。 您可能想尝试使用以下配置。

    private SecurityScheme securityScheme() {
        return new OAuthBuilder()
                .name("spring_oauth")
                .grantTypes(grantTypes())
                .build();
    }

    private SecurityContext securityContext() {
        return SecurityContext.builder()
                .securityReferences(Arrays.asList(new SecurityReference("spring_oauth", new AuthorizationScope[] {})))
                .forPaths(PathSelectors.regex("/api.*"))
                .build();
    }

    private List<GrantType> grantTypes() {
        GrantType grantType = new ClientCredentialsGrant(authTokenURL);
        return Arrays.asList(grantType);
    }

我找到了解决方案:

我将 RestController 中的 Requests 注释为 PostRequests,因为那是 keycloak 文档中指定的内容并且是有意义的。

将它们更改为 GetRequests 后,它们现在可以工作了。