.NET CORE 5、VUE 2x、Docker、JWT 总是返回 401
Posted
技术标签:
【中文标题】.NET CORE 5、VUE 2x、Docker、JWT 总是返回 401【英文标题】:.NET CORE 5, VUE 2x, Docker, JWT returns always 401 【发布时间】:2021-11-12 03:27:32 【问题描述】:我需要这个社区的帮助来解决一个非常繁琐的问题。 我正在部署一个使用 .net core 5 web api 作为后端,vue2x 作为前端的应用程序。 后端连接到 mongodb,一切都由 docker-compose 编排。 我有 JWT 身份验证和 CORS。
问题是当我在本地机器(Windows)上运行 docker-compose up 时,一切正常。
当我在我的服务器 (ubuntu) 上运行 docker-compose up 时,我无法进行身份验证,并且总是得到 401(即使使用邮递员)。
是的,我读过这个 https://docs.microsoft.com/en-gb/aspnet/core/fundamentals/middleware/?view=aspnetcore-5.0#order 和这个 ASP.NET core JWT authentication always throwing 401 unauthorized 和这个 ASP.Net Core API always returns 401 unauthorized whenever I send a request with Bearer token included.
非常烦人的是,docker 应该让我们摆脱“它在我的机器上工作”之类的问题,所以我真的不知道该往哪里砸了。
这里有一些代码
启动
public class Startup
readonly string LocalHostpecificOrigins = "_localhostSpecificOrigin";
public Startup(IConfiguration configuration)
Configuration = configuration;
public IConfiguration Configuration get;
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
#region db-config
// requires using Microsoft.Extensions.Options
services.Configure<BookstoreDatabaseSettings>(
Configuration.GetSection(nameof(BookstoreDatabaseSettings)));
services.AddSingleton<IBookstoreDatabaseSettings>(sp =>
sp.GetRequiredService<IOptions<BookstoreDatabaseSettings>>().Value);
services.AddSingleton<BookService>();
// requires using Microsoft.Extensions.Options
services.Configure<MisteryBoxDataBaseSettings>(
Configuration.GetSection(nameof(MisteryBoxDataBaseSettings)));
services.AddSingleton<IMisteryBoxDataBaseSettings>(sp =>
sp.GetRequiredService<IOptions<MisteryBoxDataBaseSettings>>().Value);
services.AddSingleton<MisteryBoxService>();
services.Configure<UserDatabaseSettings>(
Configuration.GetSection(nameof(UserDatabaseSettings)));
services.AddSingleton<IDatabaseSettings>(sp =>
sp.GetRequiredService<IOptions<UserDatabaseSettings>>().Value);
services.AddSingleton<UserService>();
#endregion
services.AddCors(options =>
options.AddPolicy(name: LocalHostpecificOrigins,
builder =>
builder.WithOrigins(
"http://localhost:8081", "http://localhost:8080",
"https://localhost:5001", "http://localhost:5000",
"http://188.166.121.146:8081", "https://188.166.121.146:8081")
.WithMethods("PUT", "DELETE", "GET", "POST")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
);
);
services.AddControllers();
services.AddAuthentication(
x =>
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
)
.AddJwtBearer(token =>
token.RequireHttpsMetadata = false;
token.SaveToken = true;
token.TokenValidationParameters = new TokenValidationParameters
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration.GetSection("JwtKey").ToString())),
ValidateIssuer = false,
ValidateAudience = false
;
);
services.AddSwaggerGen(c =>
c.SwaggerDoc("v1", new OpenApiInfo Title = "Kool_Backend", Version = "v1" );
);
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Kool_Backend v1"));
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(LocalHostpecificOrigins);
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
endpoints.MapControllers();
);
用户控制器.cs
[EnableCors("_localhostSpecificOrigin")]
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class UserController : ControllerBase
private readonly UserService _userService;
public UserController(UserService service)
_userService = service;
[HttpGet]
public ActionResult<List<User>> Get() =>
_userService.Get();
[HttpGet("id:length(24)", Name = "GetUser")]
public ActionResult<User> Get(string id)
var user = _userService.Get(id);
if (user == null)
return NotFound();
return user;
[HttpPost]
public ActionResult<User> Create(User user)
_userService.Create(user);
return CreatedAtRoute("GetUser", new id = user.Id.ToString() , user);
[HttpPut(Name = "UpdateUser")]
public IActionResult Update([FromBody] User userIn)
var user = _userService.Get(userIn.Id);
if (user == null)
return NotFound();
_userService.Update(user.Id, userIn);
return NoContent();
[AllowAnonymous]
[Route("authenticate")]
[HttpPost]
public ActionResult Login([FromBody] User user)
var token = _userService.Auhtenticate(user.Email, user.Password);
if (token == null)
return Unauthorized();
return Ok(new token, user );
Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["./Kool-Backend/Kool-Backend.csproj", "."]
RUN dotnet restore "Kool-Backend.csproj"
COPY ./Kool-Backend .
WORKDIR "/src/"
RUN dotnet build "Kool-Backend.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Kool-Backend.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Kool-Backend.dll"]
Docker 编写
version: "3.4"
services:
mongodb:
container_name: mongodb
image: mongo
volumes:
- ~/mongo/data:/data/db
ports:
- "27017:27017"
koolbackend:
image: moscaen/koolbackend
restart: unless-stopped
build:
context: .
dockerfile: ./Kool-Backend/Dockerfile
ports:
- "5001:443"
- "5000:80"
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+:443;http://+:80
- ASPNETCORE_HTTPS_PORT=5001
- ASPNETCORE_Kestrel__Certificates__Default__Password=verysecretpassword
- ASPNETCORE_Kestrel__Certificates__Default__Path=/https/Kool-Backend.pfx
volumes:
- ~/.aspnet/https:/https:ro
depends_on:
- mongodb
我省略了前端部分,因为我在与邮递员联系后端 api 时遇到问题。 当 docker-compose up 从我的本地机器(即 https://localhost:5001)运行但不在服务器上(即https://1xx.1xx.1xx.1xx:5001)运行时,它再次起作用
如果有人有什么想法,请告诉我。
谢谢,祝你有美好的一天!
PS:这里有一些截图
errors screenshot
【问题讨论】:
i.stack.imgur.com/xvPzd.png 显示 ERR_CERT_COMMON_NAME_INVALID。所以根本问题是 SSL 故障——一个 SSL 证书问题。 【参考方案1】:最后我尝试了一个更宽松的 cors 政策,它看起来很有效。
我换了
services.AddCors(options =>
options.AddPolicy(name: LocalHostpecificOrigins,
builder =>
builder.WithOrigins(
"http://localhost:8081", "http://localhost:8080",
"https://localhost:5001", "http://localhost:5000",
"http://188.166.121.146:8081", "https://188.166.121.146:8081")
.WithMethods("PUT", "DELETE", "GET", "POST")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
);
);
与
services.AddCors(options =>
options.AddPolicy("AllowAll",
builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); );
);
我已经把它移到下面了
services.AddSwaggerGen() ...
最后我在 Configure 方法中设置了 CORS
...
app.UseCors("AllowAll");
...
这允许我从控制器中删除属性。
...
[EnableCors("_localhostSpecificOrigin")]
...
简而言之,我仍然不知道是什么解决了这个问题,但这个设置现在可以工作了。
感谢大家的关注,祝您有美好的一天!
【讨论】:
以上是关于.NET CORE 5、VUE 2x、Docker、JWT 总是返回 401的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Core 5 + SQL Server Docker 容器:无效的撰写项目
。NET Core 3.1 gRPC Docker:无法使原型路径相对
小5聊Vue与.net Core 如何接收List<T>泛型参数
带有 Vue JS 的 ASP.NET Core 5 从源访问 XMLHttpRequest 已被 CORS 策略阻止