Nie działa Autoryzacja w Asp.Net Core 6.0

0

Dodalem w klasie Startup app.UseAuthorization(), a autoryzacja nadal nie działa. Bez atrybutu Authorize działa dobrze. Po wysłaniu rządania dla tej metody dostaję kod statusu 500 Internal Server Error. W nagłówku żądania dałem: Key: Authorization, Value: Bearer <zawartość tokena>. Będę wdzięczny za pomoc. Oto kod kontrolera:

[HttpGet]
[Authorize]
public ActionResult<IEnumerable<RestaurantDto>> GetAll()
{
    var restaurantsDto = _restaurantService.GetAll();

    return Ok(restaurantsDto);
}

Klasa RestaurantService:

public IEnumerable<RestaurantDto> GetAll()
{
    var restaurants = _dbContext.Restaurants
        .Include(r => r.Address)
        .Include(r => r.Dishes).ToList();

    var restarantsDto = _mapper.Map<IEnumerable<RestaurantDto>>(restaurants);
    return restarantsDto;
}
0

Oprócz app.UseAuthorization() musisz jeszcze dopisać app.UseAuthentication().

PS.
NET 6 nie ma Startup.cs. Jesteś pewny, że to NET 6?

0

@AdamWox: Mam też app.UseAuthentiaction(). A klasę Startup stworzyłem ręcznie. Autentykacja działała.

app.UseAuthentication();
app.UseMvc();
app.UseMiddleware<ErrorHandlingMiddleware>();
app.UseMiddleware<RequestTimeMiddleware>();
app.UseSwagger();
app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "Restaurant API"); });
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});
0

Może problemem nie jest autoryzacja sama w sobie tylko coś więcej. Jesteś w stanie zdebugować kod, wrzucić oprócz kodu błędu jeszcze treść tego błędu?

0

@AdamWox: Właśnie coś mi się pochrzaniło i wysyłanie żądań nie działa teraz dla żadnej metody, nawet tych dla których nie ma atrybutu Authorization. A wcześniej działało wszystko (przed tym jak dodałem app.UseAuthorization()). Dostaje tylko kod statusu 500 i nic poza tym.

0

Zakomentowałem tam gdzie dodałem autoryzacje w plikach konfiguracyjnych i teraz działają żądania.

0

Co to znaczy? Czyli co zmieniłeś? Działa ci autoryzacja?

0

Jeszcze nie. Pozniej coś pokombinuje.

0

@AdamWox: Nie wiem co jest nie tak. Dostaje cały czas kod statusu 500 podczas wysyłania żądania. Break Pointa jak stawiam przy tej metodzie to mi nie zatrzymuje się w tym miejscu, więc nie wiem co mam robić.

1

Napisz własnego handlera do requestow i tam zrób try catch. Tam będziesz mógł złapać wyjątek

https://blog.kloud.com.au/2016/11/24/implementing-http-request-handler-on-aspnet-core-applications/

0

@fasadin: Ok dzięki. W weekend to zrobie bo niedługo muszę do roboty spieprzać. Próbowałem samo try and catch, ale nie wyłapuje.

0

@fasadin: Podczas tworzenia tego middleware, w poniższym kodzie występują 2 błędy: BuildUri(url, context) - nie wykrywa tej metody i nie można jej dodać poprzez ctrl + "." oraz w miejscu foreach (var header in headers) - nie wykrywa zmiennej headers.

public class RequestMiddleware
    {
        private readonly RequestDelegate _next;


  public RequestMiddleware(RequestDelegate next)
        {
            this._next = next;

  }

        public async Task Invoke(HttpContext context)
        {
           
    await this.ProcessRequestAsync(context).ConfigureAwait(false);
        }

        private async Task ProcessRequestAsync(HttpContext context)
        {
            var uri = BuildUri(url, context);

            using (var client = new HttpClient())
            {

      // Add custom headers.
      foreach (var header in headers)
                {
                    client.DefaultRequestHeaders.Add(header.Key, header.Value);
                }

                var result = await client.GetAsync(uri).ConfigureAwait(false);

                context.Response.StatusCode = (int)result.StatusCode;
                if (result.Content.Headers.ContentType != null)
                {
                    context.Response.ContentType = result.Content.Headers.ContentType.MediaType;
                }

                var response = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
                await context.Response.WriteAsync(response, Encoding.UTF8).ConfigureAwait(false);
            }
        }

        ```
0

Trzeba czytać a nie na ślepo kopiować z nadzieją że zadziała

public async Task Invoke(HttpContext context)
  {
    try 
    {

        await this._next.Invoke(context).ConfigureAwait(false);

    }
    catch(Exception ex)
    {
    }
  }

To wystarczy do debugowania. Breakpoint dajesz na klamerce od catch

Musisz zarejestrować ta klasę jako middleware w builderze

0

@fasadin: wystarczy dodać: builder.Services.AddScoped<RequestMiddleware>(); ?

0

i potem jak to obsłużyć na tej metodzie?


[HttpGet]
[Authorize]
public ActionResult<IEnumerable<RestaurantDto>> GetAll()
{
        var restaurantsDto = _restaurantService.GetAll();

        return Ok(restaurantsDto);
}
0

W linku jest wszystko co potrzebujesz

builder.UseMiddleware<RequestMiddleWare>();

Nie musisz nic obsługiwać w żadnej metodzie.
Po odebraniu requesta ta klasa sama się wykona.
Postaw breakpoint na początku middleware to sam zobaczysz

1

@fasadin: Podkreśla mi builder i pisze, że element builder nie ma wartości null w tym miejscu oraz WebApplicationBuilder nie zaweira definicji dla UseMiddleware, a najlepsze przeciążenie metody rozszerzenia ..... wymaga odbiorcy typy IApplicationBuilder.

0

A może da się to zrobić Loggerem? Tzn wziąć tą akcję w blok try and catch i w catch dać: logger.logError(ex.Message)?

0

Dobra mam taki błąd: Configure your application startup by adding app.UseAuthorization() in the application startup code. If there are calls to app.UseRouting() and app.UseEndpoints(...), the call to app.UseAuthorization() must go between them. Endpoint RestaurantApp.Controllers.RestaurantController.GetAll (RestaurantApp) contains authorization metadata, but a middleware was not found that supports authorization. Tylko że ja mam dodane app.UseAuthorization() w tym miejsciu.

public async void Configure(IApplicationBuilder app, IWebHostEnvironment env)
 {
     app.Run(async (context) => { await context.Response.WriteAsync("Response from RequestMiddleware");
     });


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


     app.UseRequestMiddleware();

     app.UseDefaultFiles(new DefaultFilesOptions());
     app.UseStaticFiles();

     app.UseRequestMiddleware();

     app.UseAuthentication();
     app.UseMvc();
     //app.UseMiddleware<ErrorHandlingMiddleware>();
     app.UseMiddleware<RequestTimeMiddleware>();
     app.UseSwagger();
     app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "Restaurant API"); });
     app.UseRouting();
     app.UseAuthorization();
     app.UseEndpoints(endpoints =>
     {
         endpoints.MapControllers();
     });

     app.UseExceptionHandler();

 }
0

app.UseAuthentication(); powinno być koło useauthorization

 app.UseMvc();
 //app.UseMiddleware<ErrorHandlingMiddleware>();
 app.UseMiddleware<RequestTimeMiddleware>();
 app.UseSwagger();
 app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "Restaurant API"); });
 app.UseRouting();
 app.UseAuthentication();
 app.UseAuthorization();
 app.UseEndpoints(endpoints =>
 {
     endpoints.MapControllers();
 });
0

poprawiłem i dalej to samo jest.

0

@fasadin: Dodałem app.UseCors(.....); oraz var services = builder.Services; services.AddCors(); i dalej ten sam błąd.

Kod Program.cs:

var builder = WebApplication.CreateBuilder(args);

var mapperConfig = new MapperConfiguration(cfg =>
{
    cfg.AddProfile(new RestaurantMappingProfile());
});

var services = builder.Services;
services.AddCors();

// Add services to the container.
builder.Services.AddRazorPages();

builder.Services.AddControllers().AddFluentValidation();

builder.Services.AddAutoMapper(typeof(RestaurantMappingProfile));

builder.Services.AddSingleton(mapperConfig.CreateMapper());

builder.Services.AddDbContext<RestaurantDbContext>(options => options.UseSqlServer("name=ConnectionStrings:DefaultConnection"));

builder.Services.AddScoped<IRestaurantService, RestaurantService>();

builder.Services.AddScoped<IDishService, DishService>();

builder.Services.AddScoped<AuthenticationSettings>();

builder.Services.AddScoped<IAccountService, AccountService>();

builder.Services.AddScoped<IPasswordHasher<User>, PasswordHasher<User>>();

builder.Services.AddScoped<IValidator<RegisterUserDto>, RegisterUserDtoValidator>();

builder.Host.UseNLog();

builder.Services.AddScoped<ErrorHandlingMiddleware>();

var app = builder.Build();

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

    app.Use(async (context, next) =>
{
    // Do work that doesn't write to the Response.
    await next.Invoke();
    // Do logging or other work that doesn't write to the Response.
});


// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    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.UseMiddleware<ErrorHandlingMiddleware>();


app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.MapRazorPages();

app.MapControllers();

app.MapControllerRoute
(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}"
);

app.UseEndpoints(x =>
{
    x.MapGet("/ping", () => "pong");
});

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from 2nd delegate.");
});

app.UseMiddleware<RequestMiddleware>();

app.Run();
0

Coś nowego wreszcie: No authenticationScheme was specified, and there was no DefaultChallengeScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).

Coś takiego znalazłem ale nie wiem co wpisaćw miejsce kropek:

services.AddAuthentication(options =>
                    {
                        options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                    })
                .AddBasic(BasicScheme, _ => { })
                .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
                {...}
                ```
1

Ja mam tą sekcje tak

builder.Services.AddAuthentication(x =>
{
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
    x.RequireHttpsMetadata = false;
    x.SaveToken = true;
    x.TokenValidationParameters = new TokenValidationParameters
    {

        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.ASCII.GetBytes("secret_key")),
        ValidateIssuer = false,
        ValidateAudience = false
    };
});
0

Wielkie dzięki. Działa nareście.

0

Tylko, że podczas wysyłania żądania zawsze dostaje kod statusu 401 Unauthorized, pomimo że w nagłówku żądania umieściłem: Key: Authorization, Value: Bearer <zawartość tokena> i spełnia reguły autoryzacji.

0

Pokaż jak tworzysz request do API

0

request.jpg

1

Dobra już działa. Dodałem app.UseAuthentication(); w Program.cs i jest ok.

1 użytkowników online, w tym zalogowanych: 0, gości: 1