gpt4 book ai didi

c# - ASP.NET Core 3.0 Web API 路由不起作用

转载 作者:行者123 更新时间:2023-12-01 21:47:21 25 4
gpt4 key购买 nike

我正在尝试访问我的 dotnet core 3.1 解决方案中的 jwt Controller 。

这是我的 jwt Controller :

[Authorize]
[ApiController]
[Route("api/[controller]")]
public class JwtController : ControllerBase
{
#region Variables
private readonly IUserAuthorisationServices _tokenService;
private readonly IOptions<JwtTokenOptions> jwtOptions;
private readonly ILogger logger;
private readonly JsonSerializerSettings _serializerSettings;
#endregion

public JwtController(IUserAuthorisationServices tokenService,
IOptions<JwtTokenOptions> jwtOptions,
ILoggerFactory loggerFactory)
{
if (loggerFactory is null) throw new ArgumentNullException(nameof(loggerFactory));

_tokenService = tokenService ?? throw new ArgumentNullException(nameof(tokenService));

jwtOptions = jwtOptions ?? throw new ArgumentNullException(nameof(jwtOptions));
logger = loggerFactory.CreateLogger<JwtController>();
_serializerSettings = new JsonSerializerSettings {
Formatting = Formatting.Indented
};
//loggingRepository = _errorRepository;
//ThrowIfInvalidOptions(this.jwtOptions);
}

[AllowAnonymous]
[Route("authenticate")]
[HttpPost]
public async Task<IActionResult> Authenticate([FromBody] LoginViewModel model)
{
var userContext = _tokenService.Authenticate(model.Email, model.Password);

if (userContext.Principal == null) {
logger.LogInformation($"Invalid username ({model.Email}) or password ({model.Password})");
return BadRequest(new { message = "Username or password is incorrect" });
}

return Ok(await _tokenService.CreateTokenAsync(userContext).ConfigureAwait(false));
}

[Route("JWTStatus")]
[HttpGet]
public static IActionResult GetJwtStatus()
{
// It made it here so it was authenticated.
return new OkResult();
}
}

我已经逐步完成了这个过程,它到达了这个中间件,然后找不到 Controller 立即返回并同时为浏览器提供 404。

这是我用来访问此 Controller 操作的内容:

login(email: string, password: string) {
this.userLogin.Email = email;
this.userLogin.Password = password;

// Do the fetch!
const t = fetch("/api/authenticate",
{
method: "POST",
body: JSON.stringify(this.userLogin),
headers: new Headers({ "content-type": "application/json" })
})
.then(response => {

我注意到获取正在使用“api/authenticate”,当我查看 HttpRequest 时,它有相同的 url 但找不到它。

这是它在返回之前到达的中间件。

namespace JobsLedger.AUTHORISATION.API.SessionMiddleware
{
public class ConfigureSessionMiddleware
{
private readonly RequestDelegate _next;

public ConfigureSessionMiddleware(RequestDelegate next)
{
_next = next;
}

public async Task InvokeAsync(HttpContext httpContext, IUserSession userSession, ISessionServices sessionServices)
{
if (httpContext == null)
{
throw new ArgumentNullException(nameof(httpContext));
}

if (userSession == null)
{
throw new ArgumentNullException(nameof(userSession));
}

if (sessionServices == null)
{
throw new ArgumentNullException(nameof(sessionServices));
}

if (httpContext.User.Identities.Any(id => id.IsAuthenticated))
{
if (httpContext.Session.GetString("connectionString") == null) // Session needs to be set..
{
userSession.UserId = httpContext.User.Claims.FirstOrDefault(x => x.Type == "userId")?.Value;
userSession.ConnectionString = sessionServices.ConnectionStringFromUserId(userSession.UserId);
httpContext.Session.SetString("userId", userSession.UserId);
httpContext.Session.SetString("connectionString", userSession.ConnectionString);
}
else // Session set so all we need to is to build userSession for data access..
{
userSession.UserId = httpContext.Session.GetString("userId");
userSession.ConnectionString = httpContext.Session.GetString("connectionString");
}
}

// Call the next delegate/middleware in the pipeline
await _next.Invoke(httpContext).ConfigureAwait(false);
}
}
}

它应该直接跳过这个,因为还没有设置用户身份。所以它真的直接进入:

await _next.Invoke(httpContext).ConfigureAwait(false);

然后进入 Controller 操作......但它直接出现 404。

在输出窗口中我得到:

Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/2.0 POST https://localhost:44301/api/authenticate text/plain;charset=UTF-8 76
Microsoft.AspNetCore.Cors.Infrastructure.CorsService: Information: CORS policy execution successful.
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished in 17.1363ms 404

可以看到404。

怎么找不到 Action ?

可能是因为它是 https 和 http 2.0?

为了完整起见,这里是该中间件处的 httpContext:

enter image description here

更新...

我在启动时不使用 MVC,只是端点...

也许它是 Startup.cs 中的管道。这是我的 startup.cs

[assembly: NeutralResourcesLanguage("en")]

namespace JobsLedger.API {
public class Startup {
//private const string SecretKey = "needtogetthisfromenvironment";

//private readonly SymmetricSecurityKey
// _signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(SecretKey));
private readonly IWebHostEnvironment _env;
private readonly IConfiguration _configuration; // { get; }

public Startup(IWebHostEnvironment env, IConfiguration configuration) {
_env = env;
_configuration = configuration;
}


// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
// Add framework services.
services.AddCors();
services.AddControllers();
services.AddOptions();

services.AddDbContext<CATALOGContext>(options => options.UseSqlServer(_configuration.GetConnectionString("CatalogConnection"), b => b.MigrationsAssembly("JobsLedger.CATALOG")));
services.AddDbContext<DATAContext>(options => options.UseSqlServer(_configuration.GetConnectionString("TenantDbConnection"), a => a.MigrationsAssembly("JobsLedger.DATA")));


// Make authentication compulsory across the board (i.e. shut
// down EVERYTHING unless explicitly opened up).
// Use policy auth.
services.AddAuthorization(options => {
options.AddPolicy("TenantAdmin", policy => policy.RequireClaim(ClaimTypes.Role, "TenantAdmin"));
options.AddPolicy("Admin", policy => policy.RequireClaim(ClaimTypes.Role, "Admin"));
options.AddPolicy("Employee", policy => policy.RequireClaim(ClaimTypes.Role, "Employee"));
});

//services.ConfigureApplicationInjection();

// Get jwt options from app settings
var tokenOptions = _configuration.GetSection("Authentication").Get<JwtTokenOptions>();

services.AddAuthentication(x => {
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options => {
options.TokenValidationParameters = new TokenValidationParameters {
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
RequireExpirationTime = true,
ValidIssuer = tokenOptions.Issuer,
ValidAudience = tokenOptions.Audience,
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(tokenOptions.SigningKey)),
ClockSkew = TimeSpan.Zero
};
});

services
.AddDistributedMemoryCache()
.AddSession()


// Repositories - DATA
.AddScoped<IClientDATARepository, ClientDATARepository>()
.AddScoped<ILoggingDATARepository, LoggingDATARepository>()
.AddScoped<IJobDATARepository, JobDATARepository>()
.AddScoped<IBrandDATARepository, BrandDATARepository>()
.AddScoped<ITypeDATARepository, TypeDATARepository>()
.AddScoped<IStateDATARepository, StateDATARepository>()
.AddScoped<IStatusDATARepository, StatusDATARepository>()
.AddScoped<ISuburbDATARepository, SuburbDATARepository>()
.AddScoped<ICounterDATARepository, CounterDATARepository>()

// Repositories - CATALOG
.AddScoped<ITenantCATALOGRepository, TenantCATALOGRepository>()
.AddScoped<IUserCATALOGRepository, UserCATALOGRepository>()
.AddScoped<IRoleCATALOGRepository, RoleCATALOGRepository>()
.AddScoped<ICounterCATALOGRepository, CounterCATALOGRepository>()
.AddScoped<ISuburbCATALOGRepository, SuburbCATALOGRepository>()
.AddScoped<IStateCATALOGRepository, StateCATALOGRepository>()

// Business services
// Services - API
.AddScoped<IClientServices, ClientServices>()
.AddScoped<IJobServices, JobServices>()

//Services - Catalog
.AddScoped<ITenantServices, TenantServices>()
.AddScoped<IUserServices, UserServices>()
//.AddScoped<IUserValidateService, UserValidateService>()

// Services - Shared
.AddScoped<IAddressDropdownServices, AddressDropdownServices>()

//Services - Auth
.AddScoped<ICryptoService, CryptoService>()
.AddScoped<IUserAuthorisationServices, UserAuthorisationServices>()
.AddScoped<IUserSession, UserSession>()
.AddScoped<ISessionServices, SessionServices>()

// CATALOG services - Initialisations.
.AddScoped<ICATALOGCounterInitialiser, CATALOGCounterInitialiser>()
.AddScoped<ICATALOGStateInitialiser, CATALOGStateInitialiser>()
.AddScoped<ICATALOGSuburbInitialiser, CATALOGSuburbInitialiser>()
.AddScoped<IRoleInitialiser, CATALOGRoleInitialiser>()
.AddScoped<ICATALOGTenantAndUserInitialisations, CATALOGTenantAndUserInitialiser>()

// DATA Services - Initialisations.
.AddScoped<IBrandInitialiser, BrandInitialiser>()
.AddScoped<IDATACounterInitialiser, DATACounterInitialiser>()
.AddScoped<IDATAStateInitialiser, DATAStateInitialiser>()
.AddScoped<IDATASuburbInitialiser, DATASuburbInitialiser>()
.AddScoped<IStatusInitialiser, StatusInitialiser>()
.AddScoped<ITypeInitialiser, TypeInitialiser>()
.AddScoped<IVisitTypeInitialiser, VisitTypeInitialiser>()

// TESTDATA Services - Initialisations.
.AddScoped<ITESTDATAInitialisations, TESTDATAInitialisations>()
.AddScoped<ITESTDATATenantAndUserInitialisations, TESTDATATenantAndUserInitialisations>()

.AddTransient<IDATAContextFactory, DATAContextFactory>()
.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); // For getting the user.
}

public static void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
}
else {
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseExceptionHandler(options => {
options.Run(async context => {
var ex = context.Features.Get<IExceptionHandlerPathFeature>();
if (ex?.Error != null) {
Debugger.Break();
}
});
});

app.UseRouting();

// global cors policy
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());

app.UseAuthentication();
app.UseHttpsRedirection();
app.UseFileServer();
app.UseStaticFiles();
app.UseSession();
app.UseAuthorization();

app.UseConfigureSession();

app.EnsureCATALOGMigrationAndInitialise();
app.EnsureDATAMigrationsAndInitialise();

app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
}
}
}

最佳答案

好的!知道了。根据您当前的路由配置,您的路由端点是:

/authenticate // <-- not api/authenticate
/JWTStatus // <-- not api/JWTStatus

因为您正在覆盖 Controller 级别的路由。

如果您希望api/authenticateapi/JWTStatus 作为您的路由端点,那么您的操作级路由应该如下所示:

[Authorize]
[ApiController]
//Remove the controller level route from here
public class JwtController : ControllerBase
{
[AllowAnonymous]
[Route("api/authenticate")] // <-- Here it is
[HttpPost]
public async Task<IActionResult> Authenticate([FromBody] LoginViewModel model)
{
.........
}

[Route("api/JWTStatus")] // <-- Here it is
[HttpGet]
public IActionResult GetJwtStatus()
{
.......
}
}

但我的建议是遵循以下约定:

[Authorize]
[ApiController]
[Route("api/[controller]/[action]")] // <-- Here it is
public class JwtController : ControllerBase
{
[AllowAnonymous]
[HttpPost]
public async Task<IActionResult> Authenticate([FromBody] LoginViewModel model)
{
.......
}


[HttpGet]
public IActionResult GetJwtStatus()
{
......
}
}

现在不再需要操作级路由,您的端点将是:

api/Jwt/Authenticate
api/Jwt/GetJwtStatus

关于c# - ASP.NET Core 3.0 Web API 路由不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60245969/

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