web-dev-qa-db-ja.com

keycloakCORSフィルタースプリングブーツ

キークロークを使用してRESTサービスを保護しています。私は与えられたチュートリアルを参照しています ここ 。残りとフロントエンドを作成しました。これで、バックエンドにkeycloakを追加すると、フロントエンドがAPI呼び出しを行うときにCORSエラーが発生します。

SpringBootのApplication.Javaファイルは次のようになります

@SpringBootApplication
public class Application 
{
    public static void main( String[] args )
    {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public WebMvcConfigurer corsConfiguration() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/*")
                        .allowedMethods(HttpMethod.GET.toString(), HttpMethod.POST.toString(),
                                HttpMethod.PUT.toString(), HttpMethod.DELETE.toString(), HttpMethod.OPTIONS.toString())
                        .allowedOrigins("*");
            }
        };
    }
} 

Application.propertiesファイルのkeycloakプロパティは次のようになります。

keycloak.realm = demo
keycloak.auth-server-url = http://localhost:8080/auth
keycloak.ssl-required = external
keycloak.resource = tutorial-backend
keycloak.bearer-only = true
keycloak.credentials.secret = 123123-1231231-123123-1231
keycloak.cors = true
keycloak.securityConstraints[0].securityCollections[0].name = spring secured api
keycloak.securityConstraints[0].securityCollections[0].authRoles[0] = admin
keycloak.securityConstraints[0].securityCollections[0].authRoles[1] = user
keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /api/*

サンプルREST私が呼び出しているAPI

@RestController
public class SampleController {    
    @RequestMapping(value ="/api/getSample",method=RequestMethod.GET)
    public string home() {
        return new string("demo");
    }        
}

フロントエンドのkeycloak.jsonプロパティには次のものが含まれます

{
  "realm": "demo",
  "auth-server-url": "http://localhost:8080/auth",
  "ssl-required": "external",
  "resource": "tutorial-frontend",
  "public-client": true
}

私が得るCORSエラー

XMLHttpRequest cannot load http://localhost:8090/api/getSample. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access. The response had HTTP status code 401.
13
krs8888

私の例のようにCORSBeanを作成してみてください。私は最近同じことを経験しました(CORSを機能させる)。SpringBootCORSのサポートは現在MVC CORSほど堅牢でも単純でもないため、悪夢でした。

_@Bean
public FilterRegistrationBean corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);

    FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
    bean.setOrder(0);
    return bean;
}
_

これは、アプリケーション全体でOriginを受け入れるように設定した方法ですが、いくつかのパラメーターを変更すると、必要なものを複製できるはずです。すなわち。言及したメソッドのみを追加したい場合は、いくつかのaddAllowedMethod()をチェーンします。許可されるオリジンは同じであり、addMapping("/api/*")source.registerCorsConfiguration("/api/*", config);になります。

編集:

Spring Data Rest and Cors

これをみて。セバスチャンはSpringエンジニアリングチームに所属しているので、これは公式の回答を得るのとほぼ同じです。

3
Trevor Bye

コード例にアクセスできませんが、含めたコード構成に基づくと、構成が欠落しているためにSpringがCORSヘッダーを除外しているようです。

J. Westの応答は、SpringとCORSで発生した最近の問題と似ていますが、Springの例で参照されている実装は2つあるため、注意してください。 Spring Security および Spring MVC Annotations 。これらの実装は両方とも互いに独立して機能し、組み合わせることはできません。

フィルタベースのアプローチをそのまま使用する場合(要約すると)、認証ヘッダーがブラウザによってドメイン間で送信されるように、許可資格情報をtrueに設定することが重要でした。また、上記で提案した完全なコード方法を使用することをお勧めします。これにより、プロパティインジェクションまたはサービスレジストリによって複数のドメインまたは環境に展開するためのはるかに構成可能なWebアプリケーションを作成できます。

2
Michael Hibay

Access-Control-Allow-Originヘッダーは、サーバーアプリケーションへのリクエストで提供されるOriginリクエストヘッダーに基づいてサーバーアプリケーションによって設定されることになっています。通常、ブラウザは、クロスオリジンリクエストが行われていることを検知すると、リクエストにOriginヘッダーを設定します。そして、彼らはそれを許可するためにAccess-Control-Allow-Originヘッダーを期待しています。

さて、keycloakについては、同じ問題に苦労しました。 this を見ると、エラー応答の場合、keycloakはAccess-Control-Allow-Originヘッダーを追加していないようです。ただし、私にとっては、成功応答の場合でも、応答にこのヘッダーを追加していませんでした。

コードを調べてブレークポイントを追加すると、クライアントオブジェクトのwebOriginが渡されても、Originヘッダーから入力されていないため、CORSがアクセス制御応答ヘッダーを追加していないことに気付きました。

CORSビルド呼び出しの直前に次のコード行を追加することで、それを機能させることができました。

client.addWebOrigin(headers.getRequestHeader("Origin").get(0));

前:

Cors.add(request, Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).auth().allowedOrigins(client).allowedMethods("POST").exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS).build();

この変更を加えてコードをビルドし、サーバーを起動すると、次の3つのアクセス制御応答ヘッダーの取得を開始しました。

Access-Control-Expose-Headers: Access-Control-Allow-Methods 
Access-Control-Allow-Origin: http://localhost:9000 
Access-Control-Allow-Credentials: true

クライアント資格情報付与タイプを使用しています。したがって、 TokenEndpoint.Java#L47buildClientCredentialsGrantにのみ追加しました。

成功応答のバグであることを確認し、キークロークコードでクライアントオブジェクトにこれを設定するためのより良い場所を見つけるために、さらにコードダイビングを行う必要があります(クライアントオブジェクトが構築されている場所など)

ぜひお試しください。

更新:
これを取り戻します。クライアントをキークロークにルートURLとして http:// localhost:90 (フロントエンドのアプリケーションポート)として再登録し、適切なアクセス制御応答ヘッダーを取得し始めました。これがお役に立てば幸いです。

2
ritesh.garg

クライアントが認証ヘッダーを送信しているときは、allowedOrigins( "*")を使用できません。特定のオリジンURLを設定する必要があります。

0
GreyBeardedGeek

私は同じ問題でここに来て、次のようにOPTIONSメソッドのみの認証を省略して修正しました:

keycloak.securityConstraints[0].security-collections[0].omitted-methods[0]=OPTIONS

Keycloackが行うOPTIONSリクエストにはAuthenticationヘッダーが含まれていないため、これは私にとってはうまくいきました。

[〜#〜] update [〜#〜]ブラウザのキャッシュに何かがあったため、バックエンドコードの変更による実際の影響を確認できませんでした。私にとって実際に機能したのは、次のように@RestControllerレベルですべてのCORSオリジンを有効にすることだったようです。

@CrossOrigin(origins = "*")
@RestController
public class UsersApi {...}
0
Nelson Garcia