这个配置是 Spring Security 用于配置 OAuth 2.0 资源服务器的 JWT(JSON Web Token)设置。具体来说,它配置了资源服务器如何验证 JWT 令牌。
配置项解释
spring.security.oauth2.resourceserver.jwt.jwk-set-uri
:这个配置项指定了 JWT 的 JWK(JSON Web Key)集合的 URI。资源服务器会从这个 URI 获取公钥,用于验证 JWT 的签名。
详细解释
spring.security.oauth2.resourceserver
这个配置项启用 Spring Security 的 OAuth 2.0 资源服务器支持。资源服务器是指那些需要保护的 API 服务,它们会验证传入请求中的访问令牌(Access Token)。
jwt
这个配置项启用 JWT 令牌的支持。JWT 是一种紧凑的、URL 安全的令牌格式,广泛用于身份验证和信息交换。
jwk-set-uri
这个配置项指定了一个 URI,资源服务器会从这个 URI 获取 JWK 集合。JWK 是一种 JSON 数据结构,表示一组加密密钥。资源服务器使用这些密钥来验证 JWT 的签名。
示例配置
假设你的身份提供者(Identity Provider, IdP)公开了一个 JWK 集合的 URI,你可以在 application.yml
中进行如下配置:
yaml
spring:
security:
oauth2:
resourceserver:
jwt:
jwk-set-uri: https://your-identity-provider.com/.well-known/jwks.json
工作原理
- 获取 JWK 集合 :资源服务器启动时,会从配置的
jwk-set-uri
获取 JWK 集合。这些 JWK 包含了用于验证 JWT 签名的公钥。 - 验证 JWT:当资源服务器收到请求时,会从请求头中提取 JWT 令牌,并使用 JWK 集合中的公钥验证 JWT 的签名。
- 解析 JWT:如果 JWT 签名验证通过,资源服务器会解析 JWT,提取其中的声明(claims),如用户信息、权限等。
- 授权访问:根据 JWT 中的声明,资源服务器决定是否授权访问受保护的资源。
示例代码
以下是一个简单的 Spring Boot 应用程序,配置了 JWT 资源服务器:
application.yml
yaml
spring:
security:
oauth2:
resourceserver:
jwt:
jwk-set-uri: https://your-identity-provider.com/.well-known/jwks.json
SecurityConfig.java
scala
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(authorizeRequests ->
authorizeRequests
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2ResourceServer ->
oauth2ResourceServer
.jwt()
);
}
}
总结
spring.security.oauth2.resourceserver.jwt.jwk-set-uri
配置项用于指定资源服务器从哪里获取 JWK 集合,以便验证 JWT 令牌的签名。通过这个配置,资源服务器可以确保传入的 JWT 令牌是由可信的身份提供者签发的,并且未被篡改。
org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder
是 Spring Security 提供的一个类,用于解码和验证 JWT(JSON Web Token)。它是基于 Nimbus JOSE + JWT 库实现的,支持响应式编程模型。
主要功能
NimbusReactiveJwtDecoder
类的主要功能是解码和验证 JWT。它可以从 JWT 中提取声明(claims),并验证 JWT 的签名和有效性。
主要方法
- decode(String token) :解码和验证给定的 JWT 令牌,返回一个
Mono<Jwt>
,其中包含解码后的 JWT 对象。
构造方法
NimbusReactiveJwtDecoder
提供了多种构造方法,允许使用不同的方式来配置解码器:
-
使用 JWK Set URI:
arduinopublic static NimbusReactiveJwtDecoder withJwkSetUri(String jwkSetUri)
-
使用公钥:
javapublic static NimbusReactiveJwtDecoder withPublicKey(RSAPublicKey key)
-
使用密钥对:
javapublic static NimbusReactiveJwtDecoder withSecretKey(SecretKey secretKey)
示例代码
以下是一个使用 NimbusReactiveJwtDecoder
解码和验证 JWT 的示例代码:
使用 JWK Set URI
ini
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder;
import reactor.core.publisher.Mono;
public class JwtDecoderExample {
public static void main(String[] args) {
String jwkSetUri = "https://your-identity-provider.com/.well-known/jwks.json";
NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder.withJwkSetUri(jwkSetUri).build();
String token = "your-jwt-token";
Mono<Jwt> jwtMono = jwtDecoder.decode(token);
jwtMono.subscribe(jwt -> {
System.out.println("JWT Claims: " + jwt.getClaims());
}, error -> {
System.err.println("Failed to decode JWT: " + error.getMessage());
});
}
}
使用公钥
ini
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder;
import reactor.core.publisher.Mono;
import java.security.interfaces.RSAPublicKey;
import java.security.KeyFactory;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class JwtDecoderExample {
public static void main(String[] args) throws Exception {
String publicKeyPEM = "your-public-key-pem";
byte[] decoded = Base64.getDecoder().decode(publicKeyPEM);
X509EncodedKeySpec spec = new X509EncodedKeySpec(decoded);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(spec);
NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder.withPublicKey(publicKey).build();
String token = "your-jwt-token";
Mono<Jwt> jwtMono = jwtDecoder.decode(token);
jwtMono.subscribe(jwt -> {
System.out.println("JWT Claims: " + jwt.getClaims());
}, error -> {
System.err.println("Failed to decode JWT: " + error.getMessage());
});
}
}
集成到 Spring Security 配置
你可以将 NimbusReactiveJwtDecoder
集成到 Spring Security 的配置中,以便在资源服务器中使用:
kotlin
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
import org.springframework.security.web.server.SecurityWebFilterChain;
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange(exchanges -> exchanges
.pathMatchers("/public/**").permitAll()
.anyExchange().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(jwt -> jwt
.jwtDecoder(jwtDecoder())
)
);
return http.build();
}
@Bean
public ReactiveJwtDecoder jwtDecoder() {
String jwkSetUri = "https://your-identity-provider.com/.well-known/jwks.json";
return NimbusReactiveJwtDecoder.withJwkSetUri(jwkSetUri).build();
}
}
总结
NimbusReactiveJwtDecoder
是 Spring Security 提供的一个类,用于解码和验证 JWT。它支持响应式编程模型,并基于 Nimbus JOSE + JWT 库实现。通过配置 JWK Set URI、公钥或密钥对,可以灵活地使用 NimbusReactiveJwtDecoder
来验证 JWT 的签名和有效性。
QA 1
Question
这里的 jwk-set-uri 应该配置的文件是从哪来的?
Answer
jwk-set-uri
配置项指定了一个 URI,资源服务器会从这个 URI 获取 JSON Web Key (JWK) 集合。这个 URI 通常由身份提供者(Identity Provider, IdP)提供,用于公开其公钥信息,以便客户端和资源服务器可以验证 JWT 的签名。
JWK Set URI 的来源
-
身份提供者的配置 :大多数现代身份提供者(如 Auth0、Okta、Azure AD、Google Identity Platform 等)都会公开一个 JWK Set URI,用于发布其公钥信息。这个 URI 通常遵循 OpenID Connect (OIDC) 规范,并且在
.well-known
路径下可以找到。 -
OpenID Connect 发现文档:如果身份提供者支持 OpenID Connect 规范,它通常会提供一个发现文档(Discovery Document),其中包含 JWK Set URI。发现文档的 URI 通常是:
perlhttps://<identity-provider-domain>/.well-known/openid-configuration
你可以访问这个 URI,查看发现文档,其中会包含
jwks_uri
字段,指向 JWK Set URI。
示例
假设你使用的是 Auth0 作为身份提供者,Auth0 的 JWK Set URI 通常是:
perl
https://<your-auth0-domain>/.well-known/jwks.json
你可以在浏览器中访问这个 URI,查看 JWK 集合。JWK 集合是一个 JSON 对象,包含一个或多个 JWK,每个 JWK 表示一个公钥。
如何找到 JWK Set URI
- 查看身份提供者文档:大多数身份提供者的文档中会明确说明 JWK Set URI 的位置。
- OpenID Connect 发现文档 :如果身份提供者支持 OpenID Connect,可以访问发现文档,查找
jwks_uri
字段。
总结
jwk-set-uri
配置项指定了一个 URI,资源服务器会从这个 URI 获取 JWK 集合,用于验证 JWT 的签名。这个 URI 通常由身份提供者提供,并且可以在身份提供者的文档或 OpenID Connect 发现文档中找到。通过正确配置 jwk-set-uri
,资源服务器可以确保 JWT 的签名是由可信的身份提供者签发的,并且未被篡改。