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

Next.js调用Spotify授权API遭遇CORS跨域拦截问题求助

解决Next.js调用Spotify授权接口时的CORS问题

问题描述

在Next.js应用中调用Express搭建的Spotify授权接口时触发CORS错误:

从源'http://localhost:3000'访问'https://accounts.spotify.com/authorize?xxx'(重定向自'http://localhost:8888/api/login')被CORS策略阻止:请求的资源上不存在'Access-Control-Allow-Origin'头。若无需透明响应,可将请求模式设为'no-cors'以禁用CORS。

直接在浏览器地址栏访问Express接口正常,部署到Vercel也无问题,但Next.js中用fetch调用就报错。

问题根源

CORS策略仅限制跨域AJAX/fetch请求,而浏览器直接导航(地址栏输入、页面跳转)不受此限制。你之前用fetch调用/api/login,fetch会自动跟随重定向到Spotify的授权页面,但Spotify的授权页面没有配置允许localhost:3000的CORS头,因此触发错误。

解决方案

1. 前端替换调用方式:用页面跳转代替fetch

不要在Next.js中用fetch请求/api/login,而是直接通过页面跳转触发授权流程:

// Next.js组件中的登录触发函数
const handleSpotifyLogin = () => {
  window.location.href = 'http://localhost:8888/api/login';
};

2. 调整Express回调路由:处理授权后重定向回Next.js

在/api/callback路由中,获取到Spotify的access_token并拿到当前播放歌曲后,不要直接返回JSON,而是重定向回Next.js页面,同时将歌曲数据存在服务端session(需安装express-session中间件):

const callback = require('express').Router();
const querystring = require('querystring');
const request = require('request');
const session = require('express-session');

require('dotenv').config();

// 配置session(需提前在Express主文件中注册session中间件)
callback.use(session({
  secret: 'your-secret-key',
  resave: false,
  saveUninitialized: true,
  cookie: { secure: process.env.NODE_ENV === 'production' }
}));

callback.get('/', (req, res) => {
  // ... 原有获取access_token的逻辑 ...

  const options = {
    url: 'https://api.spotify.com/v1/me/player/currently-playing',
    headers: { 'Authorization': 'Bearer ' + access_token },
    json: true
  };

  request.get(options, function(error, response, body) {
    // 将歌曲数据存入session
    req.session.currentSong = body?.item 
      ? {
          name: body.item.name,
          artist: body.item.artists[0].name,
          album: body.item.album.name,
          image: body.item.album.images[0].url
        }
      : { name: '', artist: '', album: '', image: '' };

    // 重定向回Next.js的目标页面
    res.redirect('http://localhost:3000/now-playing');
  });
});

3. 新增Express接口:供Next.js获取当前歌曲数据

创建/api/get-current-song接口,从session中读取歌曲数据并返回给Next.js:

const currentSongRouter = require('express').Router();
const cors = require('cors');

currentSongRouter.use(cors({
  origin: 'http://localhost:3000',
  credentials: true // 允许携带cookie(session依赖cookie)
}));

currentSongRouter.get('/', (req, res) => {
  res.json(req.session.currentSong || { name: '', artist: '', album: '', image: '' });
});

module.exports = currentSongRouter;

4. Next.js中获取歌曲数据

在Next.js的/pages/now-playing.js页面中,调用新增的接口获取数据:

import { useEffect, useState } from 'react';

export default function NowPlaying() {
  const [songData, setSongData] = useState({});

  useEffect(() => {
    const fetchCurrentSong = async () => {
      try {
        const res = await fetch('http://localhost:8888/api/get-current-song', {
          credentials: 'include' // 携带session cookie
        });
        const data = await res.json();
        setSongData(data);
      } catch (error) {
        console.error('获取当前歌曲失败:', error.message);
      }
    };

    fetchCurrentSong();
  }, []);

  return (
    <div>
      <h2>当前播放</h2>
      {songData.image && <img src={songData.image} alt={songData.name} width={200} />}
      <p>歌曲:{songData.name}</p>
      <p>歌手:{songData.artist}</p>
      <p>专辑:{songData.album}</p>
    </div>
  );
}

额外优化建议

  • 生产环境中,将origin配置为你的Next.js域名,不要用*
  • 使用express-session时,生产环境需配置安全的cookie(secure: true)和合适的存储(如Redis),避免内存泄漏
  • 可以将Spotify的access_token存在session中,后续调用Spotify API时直接从session读取,无需重复授权

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 14:07:06