简体   繁体   English

为什么我未经授权的控制器不返回 401 ASP.Net Core?

[英]Why don't my unauthorized controllers return 401 ASP.Net Core?

I'm using Visual studio code and I'm using dot net core framework for a RestAPI.我正在使用 Visual Studio 代码,并且正在为 RestAPI 使用 dot net core 框架。 When I access do a controller with "Authorize" attribute, it should return a 401 request but it doesn't return anything in postman.当我访问带有“授权”属性的控制器时,它应该返回一个 401 请求,但它不会在邮递员中返回任何内容。 Just a blank.只是一片空白。

I think it should comes from my startup code.我认为它应该来自我的启动代码。

I'll share you my configure method in startup file.我将在启动文件中与您分享我的配置方法。

Best thanks for your help.非常感谢您的帮助。 If you can find a solution on internet, just share it (I already look for but... Maybe I didn't type the right keyword.)如果您可以在互联网上找到解决方案,只需分享它(我已经在寻找但是...也许我没有输入正确的关键字。)

public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration;公共类启动 { 公共启动(IConfiguration 配置){ 配置 = 配置; } }

    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)
    {
        ConfigureContext(services);

        services.AddCors();
        services.AddAutoMapper(typeof(Startup));

        // configure strongly typed settings objects
        var appSettingsSection = Configuration.GetSection("AppSettings");
        services.Configure<AppSettings>(appSettingsSection);

        // configure jwt authentication
        var appSettings = appSettingsSection.Get<AppSettings>();
        var key = Encoding.ASCII.GetBytes(appSettings.Secret);
        services.AddAuthentication(x =>
        {
            x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(x =>
        {
            x.Events = new JwtBearerEvents
            {
                OnTokenValidated = context =>
                {
                    var userService = context.HttpContext.RequestServices.GetRequiredService<IUserService>();
                    var userId = int.Parse(context.Principal.Identity.Name);
                    var user = userService.GetById(userId);
                    if (user == null)
                    {
                        // return unauthorized if user no longer exists
                        context.Fail("Unauthorized");
                    }
                    return Task.CompletedTask;
                }
            };
            x.RequireHttpsMetadata = false;
            x.SaveToken = true;
            x.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false
            };
        });

        // Register the Swagger generator, defining 1 or more Swagger documents
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo
            {
                Title = "dotnetcore-api-core",
                Version = "v1"
            });
        });
        services.AddScoped<IUserService, UserService>();
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseAuthentication();
        app.UseMvc();
        app.UseStaticFiles();
        app.UseHttpsRedirection();
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        // Enable middleware to serve generated Swagger as a JSON endpoint.
        app.UseSwagger();
        // Security JWT
        app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());

        // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
        // specifying the Swagger JSON endpoint.
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "dotnetcore-api-core V1");
        });
    }

    public void ConfigureContext(IServiceCollection services)
    {
        // Database injection
        services.AddDbContext<UserContext>(options =>
            options.UseMySql(Configuration.GetConnectionString("AppDatabase")));
    }
}

My controller that doesn't return 401 unauthorized:我的控制器未返回 401 未经授权:

    [Authorize]
    [Route("api/users")]
    [ApiController]
    public class UserController : ControllerBase
    {
        private readonly IUserService _userService;
        private IMapper _mapper;

        public UserController(
            IUserService userService,
            IMapper mapper)
        {
            _userService = userService;   
            _mapper = mapper;
        }

        [HttpGet]
        public async Task<ActionResult<IEnumerable<User>>> GetUsers()
        {
            IEnumerable<User> users = await _userService.GetAll();

            if(users == null)
            {
                return NotFound();
            }

            return Ok(users);
        }

I followed this tutorial -> https://jasonwatmore.com/post/2018/08/14/aspnet-core-21-jwt-authentication-tutorial-with-example-api我遵循了本教程-> https://jasonwatmore.com/post/2018/08/14/aspnet-core-21-jwt-authentication-tutorial-with-example-api

An example image in postman : Image example of empty body postman邮递员中的示例图像:空身体邮递员的图像示例

I think your problem is the same.我想你的问题是一样的。 You can add a few lines of code as below (in the Startup.cs file):您可以添加如下几行代码(在 Startup.cs 文件中):

Option 1:选项1:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseCors(pol => pol.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
    app.UseAuthentication();

    if (env.IsDevelopment())
        app.UseDeveloperExceptionPage();

    app.UseStatusCodePages(async context =>
    {
        if (context.HttpContext.Request.Path.StartsWithSegments("/api"))
        {
            if (!context.HttpContext.Response.ContentLength.HasValue || context.HttpContext.Response.ContentLength == 0)
            {
                // You can change ContentType as json serialize
                context.HttpContext.Response.ContentType = "text/plain";
                await context.HttpContext.Response.WriteAsync($"Status Code: {context.HttpContext.Response.StatusCode}");
            }
        }
        else
        {
            // You can ignore redirect
            context.HttpContext.Response.Redirect($"/error?code={context.HttpContext.Response.StatusCode}");
        }
    });

    app.UseMvc();
}

Option 2选项 2

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
       app.UseDeveloperExceptionPage();
    }

    app.UseExceptionHandler("/api/errors/500");
    app.UseStatusCodePagesWithReExecute("/api/errors/{0}");
    // or app.UseStatusCodePagesWithRedirects("~/api/errors/{0}");

    app.UseRouting();

    ...
}

Then, create ErrorController like:然后,创建 ErrorController 像:

[ApiController]
[Route("api/errors")]
public class ErrorController : Controller
{
    [HttpGet("{code}")]
    public async Task<IActionResult> Get(int code)
    {
        return await Task.Run(() =>
        {
            return StatusCode(code, new ProblemDetails()
            {
                Detail = "See the errors property for details.",
                Instance = HttpContext.Request.Path,
                Status = code,
                Title = ((HttpStatusCode)code).ToString(),
                Type = "https://my.api.com/response"
            });
        });
    }
}

I hope this helps.我希望这有帮助。

Try to move this line to the top of the Configure method:尝试将此行移动到Configure方法的顶部:

app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());

Eg:例如:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
    app.UseAuthentication();
    app.UseMvc();

    // the rest of you code here
}

Your call is returning 401. It is clearly visible in the postman.你的电话是返回 401。它在邮递员身上清晰可见。 Body is ofcourse empty, but if you look a little bit higher and on the right site (in the same line that it is body, cookies, headers tab), you will see Status line that will say 401 Unauthorised.正文当然是空的,但是如果您在正确的站点(与正文、cookie、标题选项卡在同一行中)看高一点,您将看到状态行,其中显示 401 未经授权。 It also shows you how much time did it take for this response and what is the size of the response.它还向您显示此响应花费了多少时间以及响应的大小。在此处输入图片说明

Add route to your GetUsers action :将路由添加到您的 GetUsers 操作:

    [Route("GetUsers")]
  public async Task<ActionResult<IEnumerable<User>>> GetUsers()

And call it in Postman like this ...api/Users/GetUsers并像这样在 Postman 中调用它...api/Users/GetUsers

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM