gpt4 book ai didi

reactjs - 在 Docker 中使用 React 和 Nginx 授权 Spotify

转载 作者:IT老高 更新时间:2023-10-28 21:26:03 35 4
gpt4 key购买 nike

我正在构建具有以下结构的 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

NOTE: In this project, user needs to go through two authorize/authenticate processes:

  1. 一个与我的应用程序,它生成一个原生 token (这已被处理已经)
  2. 另一个与 Spotify(需要 redirect URI 并为其 API 访问提供自己的 token)

    2a) 所以,在 localhost,无论是在 localhost/auth/registerlocalhost/auth/login 提交之后,我都会有 Spotify redirect URI (http://localhost:8888),带我到这个页面:

enter image description here

2b) 然后,点击登录按钮,系统会要求我将我的应用与 Spotify 连接,如下所示:

enter image description here

最后一次 OK 我将获得许可并交给我一个 token 我可以保存甚至刷新我的 React 客户端.


本项目的构建 block 摘自本教程:

using-spotifys-awesome-api-with-react

但是,我已经配置了一个 React client,除了这个授权过程之外,它还有其他用途。

以下是试图整合这两个服务的相关代码:更通用的clientspotify-client


相关代码:

所以我的第一个尝试是为 spotify-client 创建一个特定的服务,在 client 服务下面,将其公开到端口 8888,如下所示:

docker-compose-dev.yml

  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 上,如下所示:

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-client/Dockerfile-dev // NEW

根据 Spotify 网络文档的要求,运行不同的进程:

# 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"]

我的反向代理,我试过了:

nginx/dev.conf

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;
}

在我的前端,我为我的重定向链接创建了一个 component:

client/src/components/SpofityRedirect.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;

这里我在“/”处显示这个重定向链接。

client/src/App.jsx

import SpotifyRedirect from './components/SpotifyRedirect';

(...)
<Switch
<Route exact path='/' render={() => (
<SpotifyRedirect/>
)} />

(...)
</Switch>

更多:

spotify-client/authorization_code/app.js

(这个是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 services at command line:

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

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

$ export REACT_APP_WEB_SERVICE_URL=http://localhost


到目前为止,通过配置 aboce,当我点击 Log in with Soptify 时,我得到:

enter image description here


问题:

如何将上述配置与我的 nginx 反向代理 一起使用,以便:

  1. 为位置 / 提供我的 Spotify 的 重定向 uri http://localhost:8888 的链接
  2. 使用 Spotify 授权应用
  3. 授权完成后返回位置 '/'

最佳答案

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

 spotify-client:
ports:
- 8888:8888

如果你真的需要 nginx,那么你将需要使用 nginx 配置 + 你还需要在 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 token 。它是 React/Angular(浏览器 JS 代码)更好的选择。请记住,此流程中不存在刷新 token ,因此您还需要实现静默刷新。

关于reactjs - 在 Docker 中使用 React 和 Nginx 授权 Spotify,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55166106/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com