我有一个由SPA,Express.js服务器和ASP NET Core MVC API组成的系统。
我的服务器使用Passport.js以便与外部提供程序一起使用OAuth,因此,除了登录表单之外,我还可以在SPA中提供SSO选项。它的工作方式是,在从提供者处获取用户信息后,它会通过POST请求将此数据发送给API,以对用户进行身份验证。如果用户选择使用登录表单而不是SSO选项之一,则会使用用户的电子邮件和密码直接向API发出POST请求。
到目前为止,在本地工作我对此没有任何问题。我被要求对系统进行容器化,因此我为每个组件创建了一个Dockerfile,一个docker-compose.yml来聚合它们,运行docker-compose build和docker-compose都没有问题。
现在,运行容器,如果我通过表单选择登录,则可以毫无问题地使用我的SPA,但是如果尝试使用SSO,则向API发出POST请求时会收到ECONNREFUSED错误。很奇怪,因为我的SPA服务向同一地址发出HTTP请求没有问题。
webportal.client_1 | Error: connect ECONNREFUSED 127.0.0.1:8443
webportal.client_1 | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1142:16) {
webportal.client_1 | errno: -111,
webportal.client_1 | code: 'ECONNREFUSED',
webportal.client_1 | syscall: 'connect',
webportal.client_1 | address: '127.0.0.1',
webportal.client_1 | port: 8443,
webportal.client_1 | response: undefined
webportal.client_1 | }
这是我的Server.ts
import bodyParser from "body-parser";
import express from "express";
import session from "express-session";
import passport from "passport";
import { initialiseAuthentication } from "./auth";
import path from "path";
import http from "http";
require("dotenv").config({
path: __dirname + `/./../.env.${process.env.NODE_ENV}`,
});
const app = express();
const port = process.env.PORT || 5000;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname, "/../build")));
app.use(session({ secret: "The big secret" }));
app.get("/ping", (req, res) => {
res.send({ express: "Pong" });
});
app.use(passport.initialize());
initialiseAuthentication(app);
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname + "/../build/index.html"));
});
http.createServer(app).listen(port, '0.0.0.0');
console.log(`Listening on port ${port}`);
服务器向其发出HTTP请求的位置
import request from "superagent";
async function verifyUser(
email: string,
name: string,
provider: string,
providerId: string
) {
return await request
.post(`${process.env.BACKEND_API_URL}/authentication/externalAuth`)
.send({
Email: email,
Name: name,
Provider: provider,
ProviderId: providerId,
})
.then((res) => {
return res;
})
.catch((err) => {
console.error(err);
});
}
async function getUserById(data) {
return await request
.get(`${process.env.BACKEND_API_URL}/user/${data.Id}`)
.auth(data, { type: "bearer" })
.then((res) => {
return res;
})
.catch((err) => {
console.error(err);
});
}
export { verifyUser, getUserById };
SPA中的我的AuthenticationService.ts
import request from "superagent";
import Cookies from "js-cookie";
export async function SignIn(email: string, password: string) {
return request
.post(
`${process.env.REACT_APP_API_BACKEND_URL}/authentication/internalAuth`
)
.send({ username: email, password: password });
}
export async function GetUserInfo(userId: number) {
const jwt = Cookies.get("jwt");
return request
.get(`${process.env.REACT_APP_API_BACKEND_URL}/user`)
.query({ id: userId })
.auth(jwt as string, { type: "bearer" })
.then((res) => {
return res.body;
})
.catch((err) => console.error(err));
}
如果有人能够为我澄清并解决该问题,我将非常感激。谢谢。
编辑1:这些请求全部在HTTPS中进行,是的,我启用了允许所有内容的CORS。
编辑2:添加了Docker-Compose和Dockerfile。
Docker-Compose
version: "3"
services:
db:
image: "mcr.microsoft.com/mssql/server"
ports:
- "1433:1433"
environment:
SA_PASSWORD: "VeryStrongPassword1234"
ACCEPT_EULA: "Y"
migrations:
build:
context: .
dockerfile: migrations.Dockerfile
depends_on:
- db
api:
ports:
- "8080:80"
- "8443:443"
environment:
- ASPNETCORE_URLS=https://+:443;http://+80
- ASPNETCORE_Kestrel__Certificates__Default__Password=VeryStrongPassword123
- ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
volumes:
- ../certs/:/https/
build:
context: .
dockerfile: api.Dockerfile
depends_on:
- migrations
spa_server:
ports:
- "5000:5000"
build:
context: ../client
dockerfile: client.Dockerfile
迁移Dockerfile
#Get base SDK Image from Microsft
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 as build-env
WORKDIR /app
#Restore any dependecies
COPY ./Migrations ./Migrations
COPY ./Main/appsettings.json ./.Main/appsettings.json
COPY ./Main/appsettings.Development.json ./Main/appsettings.Development.json
COPY ./Roles.Persistence ./Roles.Persistence
COPY ./Users.Persistence ./Users.Persistence
RUN dotnet restore ./Migrations/Migrations.csproj
#Build our release
RUN dotnet publish ./Migrations/Migrations.csproj -c Release --no-restore
#Generate runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
WORKDIR /app
COPY --from=build-env /app/Migrations/bin/Release/netcoreapp3.1/publish/ .
ENTRYPOINT ["dotnet","Migrations.dll"]
API Dockerfile
#Get base SDK Image from Microsft
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 as build-env
WORKDIR /app
#Restore any dependecies
COPY . ./
RUN dotnet restore ./Main/Main.csproj
#Build our release
RUN dotnet publish ./Main/Main.csproj -c Release --no-restore
#Generate runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
WORKDIR /app
EXPOSE 80 443
COPY --from=build-env /app/Main/bin/Release/netcoreapp3.1/publish/ .
ENTRYPOINT ["dotnet","Main.dll"]
SPA和服务器Dockerfile
# Get base image from Node
FROM node:latest as build-env
WORKDIR /app
# Restore dependencies
COPY . ./
RUN npm i -g env-cmd
RUN npm i -g npm-run-all
RUN yarn
# Build client
RUN yarn build:container
# Generate image
EXPOSE 5000
ENTRYPOINT ["yarn", "start:container"]
答案 0 :(得分:0)
我解决了。
我使用的端口出了问题。 为了使SPA从浏览器发出请求,我需要使用外部端口8443。因此,在容器中运行的服务器需要调用内部端口443,而现在它的工作方式是
谢谢大家。