出于学习目的,我决定创建一个包含三个服务(Java 模块)的示例应用程序。
我对前两个没有任何大问题,但我花了最后几个小时试图弄清楚如何创建有效的 OAuth 2 客户端,但我不断收到此错误:
Unable to resolve Configuration with the provided Issuer of "http://localhost:9000"
。
由于我不知道问题出在哪里,我将提供所有 3 项服务的所有必要上下文。
这是资源服务器的配置。
application.yml
server:
port: 8080
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: "http://localhost:9000"
jwk-set-uri: "http://localhost:9000/oauth2/jwks"
SecurityConfig
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) {
return new MvcRequestMatcher.Builder(introspector);
}
@Bean
@Order(1)
public SecurityFilterChain filterChain(HttpSecurity http, MvcRequestMatcher.Builder mvc) throws Exception {
http
// SECURITY
.csrf(CsrfConfigurer::disable)
.headers(headers -> headers
.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
// RISK
.authorizeHttpRequests((auth) -> auth
.requestMatchers(mvc.pattern("/data-api/users")).denyAll()
.requestMatchers(mvc.pattern("/data-api/users/**")).denyAll()
.requestMatchers(mvc.pattern("/data-api/taco-orders")).denyAll()
.requestMatchers(mvc.pattern("/data-api/taco-orders/**")).denyAll()
.requestMatchers(mvc.pattern(HttpMethod.POST, "/data-api/tacos")).authenticated()
.requestMatchers(mvc.pattern(HttpMethod.DELETE, "/data-api/tacos/**")).denyAll()
.requestMatchers(mvc.pattern(HttpMethod.POST, "/data-api/ingredients")).hasAuthority("SCOPE_ingredients.write")
.requestMatchers(mvc.pattern(HttpMethod.DELETE, "/data-api/ingredients/**")).hasAuthority("SCOPE_ingredients.delete")
.requestMatchers(mvc.pattern("/design"), mvc.pattern("/orders")).hasRole("USER")
.requestMatchers(mvc.pattern("/"), mvc.pattern("/**")).permitAll()
.requestMatchers(toH2Console()).permitAll()
.anyRequest().authenticated())
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()))
.formLogin((formLogin) -> formLogin
.loginPage("/login")
.defaultSuccessUrl("/design"));
return http.build();
}
}
授权服务器设置...
application.yml
server:
port: 9000
AuthServerConfig
@Configuration(proxyBeanMethods = false)
public class AuthServerConfig {
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SecurityFilterChain authServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http
.formLogin(Customizer.withDefaults());
return http.build();
}
@Bean
public RegisteredClientRepository registeredClientRepository(PasswordEncoder passwordEncoder) {
RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("taco-cloud-client")
.clientSecret(passwordEncoder.encode("secret"))
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantTypes(grantTypes -> grantTypes.addAll(Set.of(
AuthorizationGrantType.AUTHORIZATION_CODE,
AuthorizationGrantType.REFRESH_TOKEN
)))
.redirectUris(redirectUris -> redirectUris.addAll(Set.of(
"http://127.0.0.1:9090/authorized",
"http://127.0.0.1:9090/login/oauth2/code/taco-cloud-client"
)))
.scopes(scopes -> scopes.addAll(Set.of(
"ingredients.write",
"ingredients.delete",
OidcScopes.OPENID
)))
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
.build();
return new InMemoryRegisteredClientRepository(registeredClient);
}
@Bean
public JWKSource<SecurityContext> jwkSource()
throws NoSuchAlgorithmException {
RSAKey rsaKey = generateRsa();
JWKSet jwkSet = new JWKSet(rsaKey);
return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
}
@Bean
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
}
private static RSAKey generateRsa() throws NoSuchAlgorithmException {
KeyPair keyPair = generateRsaKey();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
return new RSAKey.Builder(publicKey)
.privateKey(privateKey)
.keyID(UUID.randomUUID().toString())
.build();
}
private static KeyPair generateRsaKey() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
return keyPairGenerator.generateKeyPair();
}
}
SecurityConfig
@EnableWebSecurity
@Configuration
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated())
.formLogin(Customizer.withDefaults());
return http.build();
}
}
还有有问题的 OAuth 2.0 客户端:
application.yml
server:
port: 9090
spring:
security:
oauth2:
client:
registration:
taco-cloud-client:
provider: tacocloud
client-id: taco-cloud-client
client-secret: secret
authorization-grant-type: authorization_code
redirect-uri: "http://127.0.0.1:9090/login/oauth2/code/{registrationId}"
scope:
- openid
- ingredients.read
- ingredients.write
provider:
tacocloud:
issuer-uri: http://localhost:9000
SecurityConfig
@EnableWebSecurity
@Configuration(proxyBeanMethods = false)
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize ->
authorize
.anyRequest().authenticated())
.oauth2Login(oauth2Login ->
oauth2Login.loginPage("/oauth2/authorization/taco-cloud-client"))
.oauth2Client(Customizer.withDefaults());
return http.build();
}
}
呃..就是这样,我想;D如果有人能好心地为我指出正确的方向,我将不胜感激!
查看完整日志会很有帮助。然而,我认为这个问题似乎与另一个问题类似。然后你需要更新授权服务器的SecurityConfig:
@Order(Ordered.HIGHEST_PRECEDENCE) 公共SecurityFilterChain授权ServerSecurityFilterChain(HttpSecurity http)抛出异常{ OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); http.getConfigurer(OAuth2AuthorizationServerConfigurer.class).oidc(withDefaults()); 返回http .formLogin(定制器.withDefaults()) 。建造(); }