- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在 this documentation 之后使用 Keycloak 11.0.2 和 Spring Security 保护我的 Spring Boot 应用程序.
我在 application.properties
中使用了基本的 Keycloak 配置:
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 header 中发送 Keycloak 提供的 token :
'Authorization' : 'Bearer ' + this.securityService.kc.token
当我访问调用 GET
API 的 Angular 页面时,我收到一个blocked by CORS policy
错误:
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 ()
错误。
KeycloakWebSecurityConfigurerAdapter:
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests().antMatchers("/api/*").hasRole("app-manager").anyRequest().permitAll();
}
Spring 示例应用程序: https://github.com/bilaldekar/kc
Angular 示例应用程序: https://github.com/bilaldekar/kc-ang
请求 header :
最佳答案
在我看来是一个 csrf 问题。
将以下内容添加到安全配置中
http.authorizeRequests().antMatchers("/api/*").hasRole("app-manager").anyRequest().permitAll()
.and().csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
以上代码将在名为XSRF-TOKEN
的cookie 中设置CSRF token 。默认情况下,Angular 会读取此 cookie 以获取 CSRF token ,并将其添加到后续请求中。为了确保 Angular 可以读取它,我们将 Http only
设置为 False
。这有其自身的安全隐患,因为现在可以通过脚本访问 CSRF token 。如果您不想这样做,另一种方法是从响应 header 中读取 X-XSRF-TOKEN
token ,并使用 Angular 拦截器将其发送到后续请求 header 中。
更新:
在本地测试时,Angular 在 4200 上运行,Spring Boot 应用程序,Keycloak 服务器在 8080、8085 端口上运行。
通过以下步骤使用 Webpack Dev 服务器代理。 (你不再需要这个配置keycloak.cors=true
)
在 environment.ts
中更新 apiUrl
apiUrl: '', //Spring Boot API
然后在src
文件夹下添加一个proxy.conf.json
,内容如下
{
"/api": {
"target": "http://localhost:8080",
"secure": false
},
"logLevel": "debug"
}
在 angular.json
服务命令中添加代理配置
"options": {
"browserTarget": "kc-ang:build",
"proxyConfig": "src/proxy.conf.json"
}
现在您会注意到 api 请求会发送到 localhost:4200/api/* 并且会通过上述配置路由到 spring boot 应用程序。
有了这个,与 XSRF 相关的 cookie 和 header 将成为请求的一部分,您应该不会遇到任何问题。
[![示例工作版本][1]][1]
更新 2:支持 CORS
如果你的前端和后端在不同的域,如果你必须支持 CORS,那么这就是需要做的
Spring 的安全配置应该允许 CORS 作为前端的来源(在本例中为 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 更新为
apiUrl: '//localhost:8085'
在使用 Angular http 客户端进行任何写入操作(POST/PUT/DELETE)时,将 withCredentials
选项设置为 true
。 (还要确保服务器端配置支持 CORS 的方法。在上面的 CORS 配置中,我们只允许 GET 和 POST。如果您需要支持 PUT/DELETE,请确保相应地更新 CORS 配置)
在这种情况下,更新 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,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64025546/
来自 java docs 公共(public) FileWriter(String fileName) 抛出 IOException 抛出: IOException - 如果指定的文件存在但它是目录而
我使用以下代码将我的 .net 客户端(基于 CQL)连接到 3 节点 Cassandra 集群。我以 30 条记录/秒的速度(从 RabbitMQ)获取数据,并且它们顺利地存储在 cassandra
如果在读取文件时缺少字段,我应该捕获 NoSuchElementException。如果缺少一个字段,我只需要跳到文件的下一行。我的问题是,我在哪里实现我的 try/catch 代码来做到这一点?这是
我正在尝试使用 ASP.NET MVC 实现 OpeinID 登录。我正在尝试按照 http://blog.nerdbank.net/2008/04/add-openid-login-support-
学习使用 Java 进行 xml 解析,并且正在编写一个测试程序来尝试各种东西。所有测试 System.out.println() 都是我在控制台中所期望的,除了 childElement 返回 [n
我正在尝试使用 SwingUtilities 创建 JFrame Thread tt = new Thread(new Runnable() { public void run
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
我写了这段代码: MethodInfo method2 = typeof(IntPtr).GetMethod( "op_Explicit", Bind
我开始学习 Java,并且正在根据书本做一些练习。在执行此操作时,我遇到了以下错误:线程“main”java.util.InputMismatchException 中出现异常。我正在编写一个简单的程
我有一个文本文件,其中前两行是整数 m 和 n,然后有 m 行,每行都有 n 管道分隔值。我编写了一个程序,读取文件并使用文件中的值创建 m*n 数组,它工作了无数次,然后突然,使用相同的代码,使用相
所以我尝试使用在另一个类中生成的 bean 以在主应用程序中使用 package com.simon.spring.basics.properties; import org.spri
我还没有完成这个应用程序,但我希望在我的手机上看到它的样子。但是,它会强制关闭并引发 InstantiationException。 logcat 异常: 09-19 20:13:47.987: D/
我想从 UIViewController 加载一个基于 SwiftUI 的 View ,该 View 读取包本地的 json。仅 swiftUI 项目中的代码和绑定(bind)工作正常,当我利用 UI
'java.net.SocketTimeoutException:连接超时' 循环一段时间后我收到此错误。为什么我会收到 SocketTimeoutException?我该如何修复这个错误? @Ove
当有 null 值时抛出 ArgumentNullException() 是个好主意吗? This thread 没有提到在 null 上抛出的最明显的异常。 谢谢 最佳答案 ArgumentNull
我得到这个异常: NullReferenceException Object reference not set to an instance of an object at Namespace
所以其中一个方法的描述如下: public BasicLinkedList addToFront(T data) This operation is invalid for a sorted list
我正在使用 Intellij Idea,当我去生成 JavaDocs(通过工具 -> 生成 JavaDoc)时,我抛出了一个 IllegealArgumentException,没有关于发生了什么问题
我正在学习 C++ 中的互斥锁,但以下代码(摘自 N. Josuttis 的“C++ 标准库”)有问题。 我不明白为什么它会阻塞/抛出除非我在主线程中添加this_thread::sleep_for(
我正在试验 JavaFX 标签和组,通过鼠标拖动将它们移动到屏幕上。新节点从一些线程添加到动画组。但是,有时我会突然看到以下异常 - 我假设,当某些节点重叠时。但是不知道是什么问题……因为不涉及我的代
我是一名优秀的程序员,十分优秀!