使用 spring-boot-starter-oauth2-authorization-server 重定向到 /error 页面而不是 /oauth2/token

问题描述 投票:0回答:1

我正在实现 Spring 授权服务器的非常基本的示例。我已经参考了 spring 授权服务器入门文档。我已经在 SpringSuiteTool4 中为该项目创建了 Spring 入门项目。

当我运行项目并在浏览器中调用 /oauth2/token url 时,它会将其重定向到登录页面。当我输入正确的用户名和密码时,它会将我重定向到/错误页面。

这是我正在使用的代码。

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.UUID;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;

import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;

/**
 * 
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    
    @Bean
    @Order(1)
    public SecurityFilterChain webFilterChainForOAuth(HttpSecurity httpSecurity) throws Exception {
        OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(httpSecurity);
        httpSecurity.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
            .oidc(Customizer.withDefaults());

        httpSecurity.exceptionHandling(e -> e.authenticationEntryPoint(
                new LoginUrlAuthenticationEntryPoint("/login")));
        
        return httpSecurity.build();
    }
    
    @Order(2)
    @Bean
    public SecurityFilterChain appSecurity(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.authorizeHttpRequests(request -> request.anyRequest().authenticated())
            .formLogin(Customizer.withDefaults());
        
        return httpSecurity.build();
    }
    
    @Bean
    public UserDetailsService userDetailsService() {
        var userDetails = User.withDefaultPasswordEncoder()
                .username("prem")
                .password("password")
                .authorities("read")
                .build();
        
        return new InMemoryUserDetailsManager(userDetails);
    }
    
    @Bean
    public RegisteredClientRepository registeredClientRepository() {
        var registeredClients = RegisteredClient.withId(UUID.randomUUID().toString())
                .clientId("public-client-app")
                .clientSecret("secret")
                .scope(OidcScopes.OPENID)
                .scope(OidcScopes.PROFILE)
                .redirectUri("http://127.0.0.1:8083/login/oauth2/code/public-client-app")
                .authorizationGrantTypes(
                        grantType -> {
                            grantType.add(AuthorizationGrantType.AUTHORIZATION_CODE);
                            grantType.add(AuthorizationGrantType.REFRESH_TOKEN);
                            grantType.add(AuthorizationGrantType.CLIENT_CREDENTIALS);
                        }
                ).clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build()/*requireProofKey(true)*/).build();
        
        return new InMemoryRegisteredClientRepository(registeredClients);
        
    }
    
    @Bean
    public AuthorizationServerSettings authorizationServerSettings() {
        return AuthorizationServerSettings.builder()
                .tokenEndpoint("/token")
                .build();
    }
    
    @Bean
    public JWKSource<SecurityContext> jwkSource() throws NoSuchAlgorithmException {

        
        var keys = generateRSAKey();
        var publicKey = (RSAPublicKey) keys.getPublic();
        var privateKey = (RSAPrivateKey) keys.getPrivate();
        
        var rsaKey = new RSAKey.Builder(publicKey).privateKey(privateKey)
                        .keyID(UUID.randomUUID().toString()).build();
        
        JWKSet jwkSet = new JWKSet(rsaKey);
        return new ImmutableJWKSet<>(jwkSet);
        
    }
    
    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;
    }
    
    @Bean
    public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
        return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
    }
    
}

这是以下项目gradle。

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.2'
    id 'io.spring.dependency-management' version '1.1.4'
}

group = 'com.opal.web.example'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = '17'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-oauth2-authorization-server'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
    useJUnitPlatform()
}

请帮助我理解这个问题。

这是调试日志条目,它们没有给我任何线索。

[2m2024-02-20T19:04:03.429+05:30[0;39m [32m INFO[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [2m[0;39m[36mo.a.c.c.C.[Tomcat].[localhost].[/]      [0;39m [2m:[0;39m Initializing Spring DispatcherServlet 'dispatcherServlet'
[2m2024-02-20T19:04:03.429+05:30[0;39m [32m INFO[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [2m[0;39m[36mo.s.web.servlet.DispatcherServlet       [0;39m [2m:[0;39m Initializing Servlet 'dispatcherServlet'
[2m2024-02-20T19:04:03.430+05:30[0;39m [32m INFO[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [2m[0;39m[36mo.s.web.servlet.DispatcherServlet       [0;39m [2m:[0;39m Completed initialization in 1 ms
[2m2024-02-20T19:04:03.440+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [2m[0;39m[36mo.s.security.web.FilterChainProxy       [0;39m [2m:[0;39m Securing GET /oauth2/token
[2m2024-02-20T19:04:03.444+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [2m[0;39m[36mo.s.s.w.a.AnonymousAuthenticationFilter [0;39m [2m:[0;39m Set SecurityContextHolder to anonymous SecurityContext
[2m2024-02-20T19:04:03.452+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [2m[0;39m[36mo.s.s.w.s.HttpSessionRequestCache       [0;39m [2m:[0;39m Saved request http://localhost:8080/oauth2/token?continue to session
[2m2024-02-20T19:04:03.453+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-1][0;39m [2m[0;39m[36mo.s.s.web.DefaultRedirectStrategy       [0;39m [2m:[0;39m Redirecting to http://localhost:8080/login
[2m2024-02-20T19:04:03.456+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-2][0;39m [2m[0;39m[36mo.s.security.web.FilterChainProxy       [0;39m [2m:[0;39m Securing GET /login
[2m2024-02-20T19:04:11.642+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-3][0;39m [2m[0;39m[36mo.s.security.web.FilterChainProxy       [0;39m [2m:[0;39m Securing POST /login
[2m2024-02-20T19:04:11.851+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-3][0;39m [2m[0;39m[36mo.s.s.a.dao.DaoAuthenticationProvider   [0;39m [2m:[0;39m Authenticated user
[2m2024-02-20T19:04:11.853+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-3][0;39m [2m[0;39m[36m.s.ChangeSessionIdAuthenticationStrategy[0;39m [2m:[0;39m Changed session id from 3E745EDCF7CE1C679F4B66F87F44289B
[2m2024-02-20T19:04:11.853+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-3][0;39m [2m[0;39m[36mo.s.s.w.csrf.CsrfAuthenticationStrategy [0;39m [2m:[0;39m Replaced CSRF Token
[2m2024-02-20T19:04:11.853+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-3][0;39m [2m[0;39m[36mw.c.HttpSessionSecurityContextRepository[0;39m [2m:[0;39m Stored SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=prem, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, CredentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[read]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=3E745EDCF7CE1C679F4B66F87F44289B], Granted Authorities=[read]]] to HttpSession [org.apache.catalina.session.StandardSessionFacade@2009ab45]
[2m2024-02-20T19:04:11.854+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-3][0;39m [2m[0;39m[36mw.a.UsernamePasswordAuthenticationFilter[0;39m [2m:[0;39m Set SecurityContextHolder to UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=prem, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, CredentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[read]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=3E745EDCF7CE1C679F4B66F87F44289B], Granted Authorities=[read]]
[2m2024-02-20T19:04:11.854+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-3][0;39m [2m[0;39m[36mo.s.s.web.DefaultRedirectStrategy       [0;39m [2m:[0;39m Redirecting to http://localhost:8080/oauth2/token?continue
[2m2024-02-20T19:04:11.858+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-4][0;39m [2m[0;39m[36mo.s.security.web.FilterChainProxy       [0;39m [2m:[0;39m Securing GET /oauth2/token?continue
[2m2024-02-20T19:04:11.859+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-4][0;39m [2m[0;39m[36mo.s.s.w.s.HttpSessionRequestCache       [0;39m [2m:[0;39m Loaded matching saved request http://localhost:8080/oauth2/token?continue
[2m2024-02-20T19:04:11.860+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-4][0;39m [2m[0;39m[36mw.c.HttpSessionSecurityContextRepository[0;39m [2m:[0;39m Retrieved SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=prem, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, CredentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[read]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=3E745EDCF7CE1C679F4B66F87F44289B], Granted Authorities=[read]]]
[2m2024-02-20T19:04:11.860+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-4][0;39m [2m[0;39m[36mo.s.security.web.FilterChainProxy       [0;39m [2m:[0;39m Secured GET /oauth2/token?continue
[2m2024-02-20T19:04:11.868+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-4][0;39m [2m[0;39m[36mo.s.security.web.FilterChainProxy       [0;39m [2m:[0;39m Securing GET /error?continue
[2m2024-02-20T19:04:11.868+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-4][0;39m [2m[0;39m[36mw.c.HttpSessionSecurityContextRepository[0;39m [2m:[0;39m Retrieved SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=prem, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, CredentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[read]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=3E745EDCF7CE1C679F4B66F87F44289B], Granted Authorities=[read]]]
[2m2024-02-20T19:04:11.868+05:30[0;39m [32mDEBUG[0;39m [35m53207[0;39m [2m---[0;39m [2m[nio-8080-exec-4][0;39m [2m[0;39m[36mo.s.security.web.FilterChainProxy       [0;39m [2m:[0;39m Secured GET /error?continue

我尝试了不同的组合并检查了端口更改。但这些解决方案并没有奏效。 我本来以为它能正常工作。

java spring spring-security-oauth2
1个回答
0
投票

您必须设置 OAuth2 客户端并使用它来启动授权代码流程。

使用 Spring 客户端,将浏览器指向

{client-uri}/oauth2/authorization/{registration-id}

使用 Postman,在“授权”选项卡中填写 OAuth2 表单。

授权代码流的第一步是当用户重定向时,客户端重定向到授权端点,而不是稍后调用的令牌端点(根据您的conf,带有客户端ID和客户端秘密)使用授权代码从授权服务器返回客户端。

顺便说一句,如果您对 OAuth2 及其 Spring 实现了解甚少,Spring 授权服务器可能不是最佳选择...

© www.soinside.com 2019 - 2024. All rights reserved.