【问题标题】:Spring Authorization Server with AuthorizationGrantType.PASSWORD具有 AuthorizationGrantType.PASSWORD 的 Spring 授权服务器
【发布时间】:2022-12-21 12:22:36
【问题描述】:

我想用 Spring Authorization Server 项目构建一个授权服务器。现在我想使用 AuthorizationGrantType.PASSWORD。

我根据 Spring Authorization Server 项目的示例开发了一个演示项目。但是,当我尝试使用http://localhost:9000/oauth2/token?grant_type=password&username=user&password=pass(我在 Postman 中使用 client_id 和 client_secret 作为基本身份验证)请求,我得到 403。

我在这里缺少什么?

依赖关系:spring-boot-starter-web、spring-boot-starter-security、spring-security-oauth2-authorization-server(版本:0.2.2)

授权服务器配置类:

import java.security.*;
import java.security.interfaces.*;
import java.util.UUID;
import org.springframework.context.annotation.*;
import org.springframework.security.oauth2.core.*;
import org.springframework.security.oauth2.server.authorization.client.*;
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.*;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;

@Configuration(proxyBeanMethods = false)
public class AuthorizationServerConfig {
    
    @Bean
    public RegisteredClientRepository registeredClientRepository() {
        RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
                .clientId("client1")
                .clientSecret("{noop}secret")
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
                .authorizationGrantType(AuthorizationGrantType.PASSWORD)
                .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
                .build();
        return new InMemoryRegisteredClientRepository(registeredClient);
    }
    
    @Bean
    public ProviderSettings providerSettings() {
        return ProviderSettings.builder()
                .issuer("http://auth-server:9000")
                .build();
    }
    
    @Bean
    public JWKSource<SecurityContext> jwkSource() {
        RSAKey rsaKey = generateRsa();
        JWKSet jwkSet = new JWKSet(rsaKey);
        return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
    }
    
    private static RSAKey generateRsa() {
        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() {
        KeyPair keyPair;
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(2048);
            keyPair = keyPairGenerator.generateKeyPair();
        } catch (Exception ex) {
            throw new IllegalStateException(ex);
        }
        return keyPair;
    }    
}

默认安全配置类:

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.*;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@EnableWebSecurity
public class DefaultSecurityConfig {
    
    @Bean
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .cors().disable()
                .authorizeRequests(authorizeRequests ->
                        authorizeRequests
                                .anyRequest()
                                .authenticated()
                );
        return http.build();
    }
    
    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails userDetails = User.withDefaultPasswordEncoder()
                .username("user")
                .password("pass")
                .roles("USER")
                .build();
        return new InMemoryUserDetailsManager(userDetails);
    }    
}

我在日志中发现了这条消息,可能与以下内容有关:

o.s.s.w.a.i.FilterSecurityInterceptor    : Failed to authorize filter invocation [POST /oauth2/token?grant_type=password&username=user&password=pass] with attributes [authenticated]

【问题讨论】:

  • 很可能是 CORS,这是否回答了您的问题? How to configure CORS in a Spring Boot + Spring Security application?
  • @Toerktumlare 不。我禁用了 CORS,但得到了相同的响应。我也可以使用“../auth2/authorize”端点,所以它不应该与 CORS 相关。我还添加了一条日志消息来发布我发现它可能是相关的。
  • 授予类型是密码,因此您需要使用用户名和密码进行身份验证。
  • client_id:clientId grant_type:password username:username password:password 作用域:read,write

标签: spring-security spring-security-oauth2


【解决方案1】:

看起来不支持密码 grant_type。可能这就是我出错的原因。

来源:https://github.com/spring-projects/spring-authorization-server/issues/126

【讨论】:

    【解决方案2】:

    你可以实现一个密码授予模拟过滤器,请看我的例子:https://github.com/andreygrigoriev/spring_authorization_server_password_grant

    【讨论】:

      【解决方案3】:

      嗨@Andrey Grigoriev https://stackoverflow.com/users/14998237/andrey-grigoriev 你能分享一下....客户端应用程序和资源应用程序,还有。只是为了帮助集成您与客户端应用程序和资源应用程序共享的 PasswordGrant-AuthServer-app。您共享的 PasswordGrant-AuthServer-app 链接太有用了。

      【讨论】:

      猜你喜欢
      • 2020-07-27
      • 2021-03-13
      • 2022-07-30
      • 2015-03-31
      • 2017-09-21
      • 2015-05-22
      • 2015-05-14
      • 2022-11-23
      • 1970-01-01
      相关资源
      最近更新 更多