React - 使用 Nginx 在 Docker 中将 URI 重定向到 Spotify

React - handle Redirect URI to Spotify in Docker with Nginx

我的 docker 应用程序中有这个文件夹结构:

nginx/
     dev.conf
client/
      src/
         Spotify.js

这就是我从 client 调用 redirect uri 的方式:

Spotify.js

  class SpotifyAuth extends Component {

  constructor () {
    super()

  this.handleRedirect = this.handleRedirect.bind(this)
  }

  getHashParams() {
    var hashParams = {};
    var e, r = /([^&;=]+)=?([^&;]*)/g,
        q = window.location.hash.substring(1);
    e = r.exec(q)
    while (e) {
       hashParams[e[1]] = decodeURIComponent(e[2]);
       e = r.exec(q);
    }
    return hashParams;
  }

  handleRedirect = (e) => {
    axios.get("http://localhost:8888" )
    .then(response => response.json())
    .then(data => console.log(data))
    .catch((err) => { console.log(err); });
    //e.preventDefault();
  }

  render () {
    return (
      <div className='button__container'>
        <button className='button' onClick={this.handleRedirect}
        ><strong>CONNECT YOUR SPOTIFY ACCOUNT</strong>
        </button>
      </div>
    )
  }
}
export default SpotifyAuth;

docker-compose-dev.yml

 nginx:
    build:
      context: ./services/nginx
      dockerfile: Dockerfile-dev
    restart: always
    ports:
      - 80:80
      - 8888:8888

    depends_on:
      - web
      - client

  client:
    build:
      context: ./services/client
      dockerfile: Dockerfile-dev
    volumes:
      - './services/client:/usr/src/app'
      - '/usr/src/app/node_modules'
    ports:
      - 3007:3000
    environment:
      - NODE_ENV=development
      - REACT_APP_WEB_SERVICE_URL=${REACT_APP_WEB_SERVICE_URL}
    depends_on:
      - web

nginx/dev.conf

server {

  listen 80;

  location / {
    proxy_pass        http://client:3000;
    proxy_redirect    default;
    proxy_set_header  Upgrade $http_upgrade;
    proxy_set_header  Connection "upgrade";
    proxy_set_header  Host $host;
    proxy_set_header  X-Real-IP $remote_addr;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Host $server_name;
  }
}

如何正确授权并处理来自 Spotify.js 的令牌?

编辑:

我已经尝试了下面的答案提出的解决方案,首先是 localhost:8888,然后是 localhost:3000(在 Spotify dev 中都作为重定向 URL 有效)

它只适用于8888,即便如此:

应用程序转储 tokenlocalStorage,但 挂起 并在浏览器上显示以下警告:

然后,如果我单击“确定”,并且只有“如果”,它会重定向。

怎么了?

我认为你应该从 localhost 直接重定向到 spotify.com,错过 localhost:8888

我已将 localhost:8888 上的代码移动到 React 组件中,以在您重定向回来时处理重定向和访问令牌的保存。

const stateKey = 'spotify_auth_state';
const client_id = 'myid'; // Your client id
const redirect_uri = 'http://localhost:3000'; // Your redirect uri
const scope =
  'user-read-private user-read-email user-read-playback-state playlist-modify-public playlist-modify-private';

function generateRandomString(length) {
  let text = '';
  const possible =
    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

  for (let i = 0; i < length; i++) {
    text += possible.charAt(Math.floor(Math.random() * possible.length));
  }

  return text;
}

class SpotifyAuth extends React.Component {
  getHashParams() {
    const hashParams = {};
    const r = /([^&;=]+)=?([^&;]*)/g;
    const q = window.location.hash.substring(1);
    let e = r.exec(q);
    while (e) {
      hashParams[e[1]] = decodeURIComponent(e[2]);
      e = r.exec(q);
    }
    return hashParams;
  }

  componentDidMount() {
    const params = this.getHashParams();

    const access_token = params.access_token;
    const state = params.state;
    const storedState = localStorage.getItem(stateKey);
    localStorage.setItem('spotify_access_token', access_token);
    localStorage.getItem('spotify_access_token');

    if (access_token && (state == null || state !== storedState)) {
      alert('There was an error during the authentication');
    } else {
      localStorage.removeItem(stateKey);
    }

    // DO STUFF WITH ACCESS TOKEN HERE
  }

  handleRedirect() {
    const state = generateRandomString(16);
    localStorage.setItem(stateKey, state);

    let url = 'https://accounts.spotify.com/authorize';
    url += '?response_type=token';
    url += '&client_id=' + encodeURIComponent(client_id);
    url += '&scope=' + encodeURIComponent(scope);
    url += '&redirect_uri=' + encodeURIComponent(redirect_uri);
    url += '&state=' + encodeURIComponent(state);

    window.location = url;
  }

  render() {
    return (
      <div className="button__container">
        <button className="button" onClick={this.handleRedirect}>
          <strong>CONNECT YOUR SPOTIFY ACCOUNT</strong>
        </button>
      </div>
    );
  }
}

componentDidMount函数将运行加载组件时:see more here

您还可以在 OAuth2 here 上阅读更多内容,您正在使用隐式流程。