You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Postman测试Spring Boot Spotify API接口的授权异常问题

问题分析与解决方案

你的核心问题是Spring Security的默认拦截规则导致Postman请求被重定向到Spotify登录页面:

  • 浏览器请求正常,是因为你已经通过OAuth2授权码流程完成了应用的登录,Spring Security会话中保存了你的认证信息,TokenService能从SecurityContext中拿到关联的Spotify令牌。
  • Postman请求时,没有经过应用的登录流程,SecurityContext为空,Spring Security会将未认证的请求重定向到Spotify授权页面,因此返回登录页源码。
  • 你在Postman中获取的Spotify令牌是给Spotify API用的,并非用于你的Spring Boot应用自身的认证,所以无法绕过应用的登录拦截。

下面提供两种针对性解决方案:


方案一:放开API端点的认证拦截(快速测试用)

适合测试阶段,直接允许/api/spotify/**路径无需认证即可访问,同时修改控制器支持外部传入Spotify令牌:

1. 添加Spring Security配置类

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/spotify/**").permitAll() // 放开API路径的认证要求
                .anyRequest().authenticated() // 其他路径仍保持认证要求
            )
            .oauth2Login(); // 保留原有的OAuth2登录功能(供浏览器使用)
        return http.build();
    }
}

2. 修改控制器,从请求头接收Spotify令牌

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/spotify")
public class SpotifyController {

    private final SpotifyService spotifyService;

    @GetMapping("/artists/{id}")
    public ResponseEntity<ArtistDto> getArtist(
            @PathVariable String id,
            @RequestHeader("Authorization") String authHeader) {
        // 提取Bearer Token(格式为 "Bearer xxxxxx")
        String accessToken = authHeader.replace("Bearer ", "");
        ArtistDto artistDto = spotifyService.getArtist(id, accessToken);
        return ResponseEntity.ok(artistDto);
    }
}

使用方式

Postman请求时,在请求头中添加Authorization: Bearer {你的Spotify令牌},即可正常获取数据。


方案二:使用Client Credentials模式自动获取令牌(生产推荐)

如果只需访问Spotify公开数据,无需用户授权,改用Client Credentials授权模式,让应用自动获取并维护Spotify令牌,无需依赖用户登录:

1. 修改application.properties

添加Client Credentials类型的客户端配置:

# 原有授权码模式配置保留(供浏览器使用)
spring.security.oauth2.client.registration.spotify.client-id=${SPOTIFY_CLIENT_ID}
spring.security.oauth2.client.registration.spotify.client-secret=${SPOTIFY_CLIENT_SECRET}
spring.security.oauth2.client.registration.spotify.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.spotify.redirect-uri=http://localhost:8080/login/oauth2/code/spotify
spring.security.oauth2.client.registration.spotify.scope=user-read-email,user-read-private
spring.security.oauth2.client.provider.spotify.authorization-uri=https://accounts.spotify.com/authorize
spring.security.oauth2.client.provider.spotify.token-uri=https://accounts.spotify.com/api/token
spring.security.oauth2.client.provider.spotify.user-info-uri=https://api.spotify.com/v1/me
spring.security.oauth2.client.provider.spotify.user-name-attribute=id

# 添加Client Credentials模式配置
spring.security.oauth2.client.registration.spotify-cc.client-id=${SPOTIFY_CLIENT_ID}
spring.security.oauth2.client.registration.spotify-cc.client-secret=${SPOTIFY_CLIENT_SECRET}
spring.security.oauth2.client.registration.spotify-cc.authorization-grant-type=client_credentials
spring.security.oauth2.client.provider.spotify-cc.token-uri=https://accounts.spotify.com/api/token

2. 修改TokenService,支持Client Credentials模式

@Service
@RequiredArgsConstructor
public class TokenService {
    private final OAuth2AuthorizedClientManager authorizedClientManager;

    public String getClientCredentialsAccessToken() {
        OAuth2AuthorizeRequest request = OAuth2AuthorizeRequest
                .withClientRegistrationId("spotify-cc")
                .principal("client")
                .build();
        OAuth2AuthorizedClient client = authorizedClientManager.authorize(request);
        return client.getAccessToken().getTokenValue();
    }
}

3. 在SecurityConfig中添加OAuth2AuthorizedClientManager Bean

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/spotify/**").permitAll()
                .anyRequest().authenticated()
            )
            .oauth2Login();
        return http.build();
    }

    @Bean
    public OAuth2AuthorizedClientManager authorizedClientManager(
            ClientRegistrationRepository clientRegistrationRepository,
            OAuth2AuthorizedClientService authorizedClientService) {
        // 配置支持Client Credentials模式的客户端提供者
        OAuth2AuthorizedClientProvider provider = OAuth2AuthorizedClientProviderBuilder.builder()
                .clientCredentials()
                .build();
        DefaultOAuth2AuthorizedClientManager manager = new DefaultOAuth2AuthorizedClientManager(
                clientRegistrationRepository, authorizedClientService);
        manager.setAuthorizedClientProvider(provider);
        return manager;
    }
}

4. 修改控制器,使用自动获取的令牌

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/spotify")
public class SpotifyController {

    private final SpotifyService spotifyService;
    private final TokenService tokenService;

    @GetMapping("/artists/{id}")
    public ResponseEntity<ArtistDto> getArtist(@PathVariable String id) {
        // 自动获取Client Credentials模式的令牌
        String accessToken = tokenService.getClientCredentialsAccessToken();
        ArtistDto artistDto = spotifyService.getArtist(id, accessToken);
        return ResponseEntity.ok(artistDto);
    }
}

使用方式

Postman直接发起GET请求http://localhost:8080/api/spotify/artists/{艺人ID}即可,无需手动添加令牌,应用会自动处理。


内容的提问来源于stack exchange,提问作者MCoffee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 17:17:32