<Spring 安全性>客户端调用资源服务器时,标头中不包含访问令牌



大家好,我正在学习Spring Security。我试图生产一个OAuth2客户端和资源服务器设置,基本上遵循https://dzone.com/articles/implement-oauth-20-easily-with-spring-boot-and-spr上的指导方针。

当试图从客户端调用资源服务器上的端点时,它给出一个HTTP 401。

2021-03-04 21:38:33.355 ERROR 99501 --- [ctor-http-nio-2] reactor.core.publisher.Operators         : Operator called default onErrorDropped
reactor.core.Exceptions$ErrorCallbackNotImplemented: org.springframework.web.reactive.function.client.WebClientResponseException$Unauthorized: 401 Unauthorized from GET http://localhost:8081/api/resource/hello
Caused by: org.springframework.web.reactive.function.client.WebClientResponseException$Unauthorized: 401 Unauthorized from GET http://localhost:8081/api/resource/hello
at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:181) ~[spring-webflux-5.3.4.jar:5.3.4]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
|_ checkpoint ⇢ 401 from GET http://localhost:8081/api/resource/hello [DefaultWebClient]
Stack trace:
at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:181) ~[spring-webflux-5.3.4.jar:5.3.4]
at 

资源服务器上的端点由OAuth2保护。假设在提供凭据(在本例中为okta)之后,在反向通道中,客户端应用程序将获得授权代码,然后将其交换为访问令牌,然后在调用资源服务器上的端点时在标头中包含访问令牌(如果我误解了,请纠正)。

以上都是在反向通道中完成的,我不确定客户端是如何调用资源服务器的。

我试图删除spring安全依赖项以禁用资源服务器上的OAuth2。在这种情况下,对资源服务器的调用没有问题。

我已经把源代码放在GitHub上。

客户
  • 资源服务器

资源服务器的密钥文件如下

OAuth2资源服务器HTTP安全配置

package com.somecompany.configuration;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and()
.authorizeRequests()
.antMatchers("/", "/error", "/webjars/**", "/actuator/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.oauth2ResourceServer()
.jwt();
}
}

OAuth2资源服务器控制器

package com.somecompany.controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/resource")
public class Oauth2DemoResourceServerController {
@GetMapping("/hello")
@CrossOrigin
public String api() {
return "Made it to protected api on resource server!";
}
}

OAuth2资源服务器属性

management.endpoints.web.exposure.include: httptrace
spring:
security:
oauth2:
resourceserver:
jwt:
jwk-set-uri: https://dev-27548664.okta.com/oauth2/default/v1/keys

OAuth2资源服务器pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.somecompany</groupId>
<artifactId>oauth2-demo-resource-server</artifactId>
<version>1.0.0</version>
<name>oauth2-demo-resource-server</name>
<description>oauth2-demo-resource-server</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

[2021年3月31日更新]

我在资源服务器上添加了一个过滤器,它显示对资源服务器的请求不包括身份验证头,因此期望401。因此,我怀疑这是WebClient配置上的问题。请看看有没有什么好主意。

我通过使用servlet方法更改WebClient配置,以某种方式使设置工作。
总之,问题是在客户端,而不是在资源服务器。

(1)在客户端的WebClient配置中,使用ClientRegistrationRepository而不是ReactiveClientRegistrationRepository(即只需遵循https://dzone.com/articles/implement-oauth-20-easily-with-spring-boot-and-spr中所描述的教程)。

(2)添加"spring-boot-starter-web";依赖。这一步很重要,因为没有它,就无法找到ClientRegistrationRepository bean。

(3)更新pom.xml以刷新依赖项。

(4)修改RestController中Webclient的用法,使用block()同步等待资源服务器的响应。


虽然安装正在工作,但我不确定如何配置安装以使用ReactiveClientRegistrationRepository使用异步方法。如果有任何人有任何想法,请随时分享,谢谢。

注:所有更改都已更新到上面提到的Git repo供您参考

相关内容

  • 没有找到相关文章

最新更新