在Docker中使用React和Nginx授权Spotify

时间:2019-03-14 15:16:51

标签: reactjs docker nginx npm spotify

我正在构建具有以下结构的dockerized REST API应用:

../
  web/
  nginx/
       dev.conf   
       Dockerfile-dev  
  client/
        build/
        conf/
        Dockerfile-dev
        node_modules/
        package_json
        public/
        src/
           App.jsx   
           components/ 
                     SpotifyRedirect.jsx                  
 spotify-client/ 
                Dockerfile-dev
                node_modules
                package-lock.json
                package.json
                authorization_code/
                                  app.js 

  

注意::在此项目中,用户需要经历两个授权/验证过程:

    我的应用程序中有
  1. 个,它会生成本机token(已解决) 已经)
  2. 另一个是Spotify(需要redirect URI并提供自己的token用于API访问)

    2a)因此,在localhostlocalhost/auth/register提交之后,我将有localhost/auth/login Spotifyredirect URI),带我到此页面:

enter image description here

2b)然后,单击登录按钮,将要求我将我的应用程序与Spotify连接,如下所示:

enter image description here

最后一个http://localhost:8888会授予我权限,并交给了OK,我可以保存它甚至在我的token客户端上刷新。


该项目的构建基块是从本教程中提取的:

using-spotifys-awesome-api-with-react

但是,我已经配置了React React,除了此授权过程之外,它还具有其他目的。

以下是试图集成这两个服务的相关代码:更通用的clientclient


相关代码:

所以我的第一个尝试是为spotify-client服务下方的spotify-client创建一个特定的服务,将其暴露给端口8888,如下所示:

  

docker-compose-dev.yml

client

然后,我将每个节点进程设置为自己的 nginx: build: context: ./services/nginx dockerfile: Dockerfile-dev restart: always ports: - 80:80 depends_on: - web - client - spotify-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 spotify-client: // NEW build: context: ./services/spotify-client dockerfile: Dockerfile-dev volumes: - './services/spotify-client:/usr/src/app' - '/usr/src/app/node_modules' ports: - 3000:8888 - 8888:3000 environment: - NODE_ENV=development - REACT_APP_WEB_SERVICE_URL=${REACT_APP_WEB_SERVICE_URL} depends_on: - web - client ,如下所示:

  

客户端/ Dockerfile-dev

Dockerfile

  

spotify-client / Dockerfile-dev //新建

根据# base image FROM node:11.6.0-alpine # set working directory WORKDIR /usr/src/app # add `/usr/src/app/node_modules/.bin` to $PATH ENV PATH /usr/src/app/node_modules/.bin:$PATH # install and cache app dependencies COPY package.json /usr/src/app/package.json RUN npm install --silent RUN npm install react-scripts@2.1.2 -g --silent # start app CMD ["npm", "start"] 网络文档的要求,该进程运行的进程不同:

Spotify

我的反向代理,我已经尝试过:

  

nginx / dev.conf

# base image
FROM node:11.6.0-alpine

# set working directory
WORKDIR /usr/src/app/authorization_code

# add `/usr/src/app/node_modules/.bin` to $PATH
ENV PATH /usr/src/app/node_modules/.bin:$PATH

# install and cache app dependencies
COPY package.json /usr/src/app/package.json
RUN npm install --silent
RUN npm install react-scripts@2.1.2 -g --silent

# start app <-- NOT npm start
CMD ["node", "app.js"] 

在前端,我为重定向链接创建一个server { listen 80; listen 8888; // NEW 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; } location /auth { // <-- app authorization, not Spotify's proxy_pass http://web:5000; 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; }

  

client / src / components / SpofityRedirect.jsx

component

在这里,我在'/'处显示此重定向链接。

  

client / src / App.jsx

import React, { Component } from 'react';

class SpotifyRedirect extends Component{
    render(){
        return (
            <div className='SpotifyRedirect'>
                <a href='http://localhost:8888'> Log in with Spotify </a>
            </div>
        );
    }
}

export default SpotifyRedirect;

更多:

  

spotify-client / authorization_code / app.js

(这是import SpotifyRedirect from './components/SpotifyRedirect'; (...) <Switch <Route exact path='/' render={() => ( <SpotifyRedirect/> )} /> (...) </Switch> 提供的,我只插入了Spofity

http://localhost:3000

  

var express = require('express'); // Express web server framework var request = require('request'); // "Request" library var cors = require('cors'); var querystring = require('querystring'); var cookieParser = require('cookie-parser'); var client_id = 'is'; // Your client id var client_secret = 'secret'; // Your secret var redirect_uri = 'http://localhost:8888'; // Your redirect uri /** * Generates a random string containing numbers and letters * @param {number} length The length of the string * @return {string} The generated string */ var generateRandomString = function(length) { var text = ''; var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; for (var i = 0; i < length; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); } return text; }; var stateKey = 'spotify_auth_state'; var app = express(); app.use(express.static(__dirname + '/public')) .use(cors()) .use(cookieParser()); app.get('/login', function(req, res) { var state = generateRandomString(16); res.cookie(stateKey, state); // your application requests authorization var scope = 'user-read-private user-read-email user-read-playback-state playlist-modify-public playlist-modify-private'; res.redirect('https://accounts.spotify.com/authorize?' + querystring.stringify({ response_type: 'code', client_id: client_id, scope: scope, redirect_uri: redirect_uri, state: state })); }); app.get('/callback', function(req, res) { // your application requests refresh and access tokens // after checking the state parameter var code = req.query.code || null; var state = req.query.state || null; var storedState = req.cookies ? req.cookies[stateKey] : null; if (state === null || state !== storedState) { res.redirect('/#' + querystring.stringify({ error: 'state_mismatch' })); } else { res.clearCookie(stateKey); var authOptions = { url: 'https://accounts.spotify.com/api/token', form: { code: code, redirect_uri: redirect_uri, grant_type: 'authorization_code' }, headers: { 'Authorization': 'Basic ' + (new Buffer(client_id + ':' + client_secret).toString('base64')) }, json: true }; request.post(authOptions, function(error, response, body) { if (!error && response.statusCode === 200) { var access_token = body.access_token, refresh_token = body.refresh_token; var options = { url: 'https://api.spotify.com/v1/me', headers: { 'Authorization': 'Bearer ' + access_token }, json: true }; // use the access token to access the Spotify Web API request.get(options, function(error, response, body) { console.log(body); }); // we can also pass the token to the browser to make requests from there res.redirect('http://localhost:3000/#' + //NEW querystring.stringify({ access_token: access_token, refresh_token: refresh_token })); } else { res.redirect('/#' + querystring.stringify({ error: 'invalid_token' })); } }); } }); app.get('/refresh_token', function(req, res) { // requesting access token from refresh token var refresh_token = req.query.refresh_token; var authOptions = { url: 'https://accounts.spotify.com/api/token', headers: { 'Authorization': 'Basic ' + (new Buffer(client_id + ':' + client_secret).toString('base64')) }, form: { grant_type: 'refresh_token', refresh_token: refresh_token }, json: true }; request.post(authOptions, function(error, response, body) { if (!error && response.statusCode === 200) { var access_token = body.access_token; res.send({ 'access_token': access_token }); } }); }); console.log('Listening on 8888'); app.listen(8888); ______ 服务在命令行:

Docker

最后,在构建之前,我运行:

  

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0e9870a7412c dev3_nginx "nginx -g 'daemon of…" 9 seconds ago Up 6 seconds 0.0.0.0:80->80/tcp dev3_nginx_1 e6bc5bbff630 dev3_spotify-client "node app.js" 26 minutes ago Up 26 minutes 0.0.0.0:3000->8888/tcp dev3_spotify-auth-server_1 a6b9e84953a3 dev3_client "npm start" 25 hours "/start.sh" 25 hours ago Up 25 hours 80/tcp, 0.0.0.0:3008->8080/tcp 16fb623ca2b3 dev3_web "/usr/src/app/entryp…" 25 hours

     

到目前为止,在配置上,当我单击Log in with Soptify时,我得到:

enter image description here


问题:

如何在$ export REACT_APP_WEB_SERVICE_URL=http://localhost上使用上面的配置,以便:

  1. 提供位置 / ,并提供我的nginx reverse proxy重定向uri http://localhost:8888
  2. 的链接
  3. 使用Spotify授权应用
  4. 完成授权后,最后回到位置'/'吗?

2 个答案:

答案 0 :(得分:4)

问题:端口8888上没有容器在监听。您可以直接在端口8888上发布spotify-client:8888(无nginx)。更新docker-compose-dev.yml

 spotify-client:
    ports:
      - 8888:8888

如果您确实需要nginx,那么您将需要使用nginx config +您还需要在端口8888上发布nginx。 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;
    }
    location /auth {
      proxy_pass        http://web:5000;
      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;
    }
  }

  # reverse proxy on the port 8888 for spotify-client
  server {
    listen  8888;
    location / {
      proxy_pass http://<spotify-client service/ip>:<port>/;
      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;
    }
  }

docker-compose-dev.yml和nginx发布的端口:

  nginx:
    ports:
      - 80:80
      - 8888:8888

通常,您需要正确配置nginx:8888-> spotify-client:port

恕我直言:您根本不需要spotify-client服务。只需在您的应用中使用implicit flow即可获得Spotify令牌。对于React / Angular(浏览器JS代码),它是更好的选择。请记住,刷新令牌在此流中不存在,因此您还需要实现静默刷新。

答案 1 :(得分:0)

当您决定使用nginx时,需要编辑配置并在端口8888上发布nginx。