带有Keycloak的Angular/Spring Boot抛出403 [英] Angular/Spring Boot with Keycloak throws 403

查看:199
本文介绍了带有Keycloak的Angular/Spring Boot抛出403的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遵循此文档,使用Keycloak 11.0.2和Spring Security保护了我的Spring Boot应用程序.

I secured my Spring Boot application with Keycloak 11.0.2 and Spring Security following this documentation.

我在application.properties中使用了基本的Keycloak配置:

I used the basic Keycloak configuration in application.properties:

    keycloak.auth-server-url=http://localhost:8085/auth
    keycloak.realm=cirta
    keycloak.resource=cirta-api
    keycloak.public-client=false

我有一个单独的前端Angular应用程序,该应用程序在Keylocak中配置为其他客户端;但与Spring Boot应用程序处于同一领域.从Angular应用程序中,我使用以下命令在HTTP标头中发送Keycloak提供的令牌:

I have a separate frontend Angular app, that is configured as a different client in Keylocak; but in the same realm as the Spring Boot app. From the Angular app I am sending the Keycloak-provided token in the HTTP headers with:

'Authorization' : 'Bearer ' + this.securityService.kc.token

当我访问调用GET API的Angular页面时,出现blocked by CORS policy错误:

When I access an Angular page that calls a GET API, I get a blocked by CORS policy error:

Access to XMLHttpRequest at 'http://localhost:8080/api/modePaiements' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.

所以我尝试将keycloak.cors=true属性添加到application.properties.添加该属性后,GET调用即可正常工作.但是现在当我调用POST/PUT API时,出现了Failed to load resource: the server responded with a status of 403 ()错误.

So I've tried adding the keycloak.cors=true property to application.properties. With that property added, the GET calls are working. But now when I call a POST/PUT API I'm getting a Failed to load resource: the server responded with a status of 403 () error.

KeycloakWebSecurityConfigurerAdapter:

@Override
protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);
    http.authorizeRequests().antMatchers("/api/*").hasRole("app-manager").anyRequest().permitAll();
}

春季示例应用程序: https://github.com/bilaldekar/kc

Angular示例应用程序: https://github.com/bilaldekar/kc-ang

请求标头:

推荐答案

给我一​​个csrf问题.

Looks to me a csrf issue.

将以下内容添加到安全配置中

Add the following to the security config

http.authorizeRequests().antMatchers("/api/*").hasRole("app-manager").anyRequest().permitAll()
                .and().csrf()
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());

上面的代码将在名为XSRF-TOKEN的cookie中设置CSRF令牌. Angular默认情况下会读取该cookie以获取CSRF令牌,并将其添加到后续请求中.为了确保Angular可以读取它,我们将Http only设置为False.这具有其自身的安全隐患,因为现在可以通过脚本访问CSRF令牌.如果您不喜欢这样做,另一种方法是从响应标头中读取X-XSRF-TOKEN令牌,然后使用Angular拦截器将其发送到后续的请求标头中.

The above code will set the CSRF token in the cookie named XSRF-TOKEN. Angular reads this cookie for CSRF tokens by default and adds this in the subsequent requests. To make sure Angular can read it, we are setting the Http only to False. This has its own security implications as the CSRF token can be accessed via script now. If you don't prefer to do this, the other way would be to read the X-XSRF-TOKEN token from the response header and send it in the subsequent request header using Angular interceptor.

更新:

在本地测试时,Angular在4200上运行,Spring Boot应用程序在8080、8085端口上运行Keycloak服务器.

When testing locally, where Angular is running on 4200, the Spring Boot app, the Keycloak server on 8080, 8085 ports.

通过以下步骤使用Webpack Dev服务器代理. (您不再需要此配置keycloak.cors=true)

Use the Webpack Dev server proxy with the following steps. (You don't need this config anymore keycloak.cors=true)

更新apiUrl

apiUrl: '', //Spring Boot API

然后在src文件夹下添加具有以下内容的proxy.conf.json

then add a proxy.conf.json under the src folder with the following content

{
    "/api": {
        "target": "http://localhost:8080",
        "secure": false
    },
    "logLevel": "debug"
}

angular.json serve命令中添加代理配置

Add the proxy config in the angular.json serve command

"options": {
    "browserTarget": "kc-ang:build",
    "proxyConfig": "src/proxy.conf.json"
}

现在,您会注意到api请求将转到localhost:4200/api/*,并将通过上述配置路由到spring boot应用.

Now you would notice the api requests would go to localhost:4200/api/* and that would be routed to the spring boot app via the above config.

与此相关,与XSRF相关的cookie和标头将成为请求的一部分,并且您应该不会遇到任何问题.

With this the XSRF related cookies and the header would be part of the request and you should not get any issues.

[![示例工作版本] [1]] [1]

[![Sample working version][1]][1]

更新2:支持CORS

Update 2: Support CORS

如果您的前端和后端位于不同的域上,并且您必须支持CORS,则需要这样做

If your frontend and backend are on different domains and if you must support CORS, then this is what needs to be done

Spring上的安全配置应允许CORS作为前端的来源(在本例中为http://localhost:4200):

The security config on Spring should allow CORS for the origin of the frontend (in this case http://localhost:4200):

protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);
    http.authorizeRequests().antMatchers("/api/*").hasRole("app-manager").anyRequest()
            .permitAll()
    .and().csrf()
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
    .and().cors();
}

@Bean
CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
    configuration.setAllowedMethods(Arrays.asList("GET","POST"));
    configuration.setAllowCredentials(Boolean.TRUE);
    configuration.addAllowedHeader("*");

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/api/*", configuration);
    return source;
}

在Angular上,将environment.ts文件中的apiUrl更新为

On Angular, update the apiUrl in environment.ts file to

apiUrl: '//localhost:8085'

在使用Angular http客户端进行任何写操作(POST/PUT/DELETE)时,请将withCredentials选项设置为true. (还要确保服务器端配置中的CORS支持该方法.在上面的CORS配置中,我们仅允许GET和POST.如果需要支持PUT/DELETE,请确保相应地更新CORS配置.)

While making any write operations (POST/PUT/DELETE) using the Angular http client, set the withCredentials option to true. (Also ensure the method is supported for CORS on the server side config. In the above CORS config we have allowed GET and POST only. If you need to support PUT/DELETE ensure you update the CORS configuration accordingly)

在这种情况下,请在fournisseur.service.ts

addFournisseur(fournisseur: Fournisseur): Observable<Fournisseur> {
    return this.httpClient.post<Fournisseur>(this.envUrl + '/api/fournisseurs', fournisseur, {withCredentials: true});
  }

这篇关于带有Keycloak的Angular/Spring Boot抛出403的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆