.NET Core 6中的授权返回400?

huangapple go评论74阅读模式
英文:

Authorization in .NET Core 6 returns 400?

问题

我是.NET Core的新手,所以我决定在这里寻求帮助。

我在创建我的Web应用程序的身份验证功能时遇到了问题。

问题是,我得到了错误响应400。如果我更改我的Program.cs中的某些配置,比如删除以下代码行:

options.Events = new JwtBearerEvents
{
    OnMessageReceived = context =>
    {
        context.Token = context.Request.Cookies["jwt"];
        return Task.CompletedTask;
    }
};

它将返回错误响应401

以下是我的Program.cs中的代码:

var builder = WebApplication.CreateBuilder(args);

// 将服务添加到容器中。
builder.Services.AddControllersWithViews();

builder.Services.AddDbContext<ApplicationDBContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("Dev_Environment")));

builder.Services.AddIdentity<LoginModel, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDBContext>()
    .AddDefaultTokenProviders();

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
    options.Events = new JwtBearerEvents
    {
        OnMessageReceived = context =>
        {
            context.Token = context.Request.Cookies["jwt"];
            return Task.CompletedTask;
        }
    };
    options.SaveToken = true;
    options.RequireHttpsMetadata = false;
    options.TokenValidationParameters = new TokenValidationParameters()
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidIssuer = builder.Configuration["Hashing:ValidIssuer"],
        ValidAudience = builder.Configuration["Hashing:ValidAudience"],
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Hashing:SecretKey"]))
    };
});

builder.Services.AddAuthorization(options =>
{
    var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
        JwtBearerDefaults.AuthenticationScheme);

    defaultAuthorizationPolicyBuilder =
        defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();

    options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
});

var app = builder.Build();

// 配置HTTP请求管道。
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

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

app.UseRouting();

app.UseAuthentication();

app.UseAuthorization();

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

app.Run();

我已经创建了一个带有属性[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]DashboardController

这是我的AuthenticationController,用于创建JWT令牌以进行授权。

[HttpPost]
public IActionResult Login(LoginModel userCredential, string returnURL)
{
    systemLogic = new AuthenticationLogic();

    if (userCredential != null)
    {
        userCredential.Email = hasher.Encrypt(userCredential.Email);
        userCredential.Password = hasher.Encrypt(clearText: userCredential.Password);
    }

    userInput = new UserInput();

    userInput[typeof(LoginModel).FullName] = userCredential;

    systemResult = systemLogic.ExecuteProcess(configuration, userInput);

    if (systemResult.ResultCode == SystemResult.SUCCESS)
    {
        LoginModel? userInfo = systemResult[typeof(LoginModel).FullName] as LoginModel;

        Claim[] claims = new[] { new Claim(ClaimTypes.Email, hasher.Decrypt(userInfo.Email)) };

        SymmetricSecurityKey secretKey = new(Encoding.UTF8.GetBytes(configuration["Hashing:SecretKey"]));

        SigningCredentials signinCredentials = new(secretKey, SecurityAlgorithms.HmacSha256);

        JwtSecurityToken tokenOptions = new(
            issuer: configuration["Hashing:ValidIssuer"],
            audience: configuration["Hashing:ValidAudience"],
            claims: claims,
            expires: DateTime.Now.AddHours(1),
            signingCredentials: signinCredentials);

        string tokenString = new JwtSecurityTokenHandler().WriteToken(tokenOptions);

        Response.Cookies.Append("jwt", tokenString, new CookieOptions
        {
            HttpOnly = true,
            SameSite = SameSiteMode.Strict,
            Secure = true,
            Expires = DateTime.UtcNow.AddDays(7)
        });

        if (!string.IsNullOrEmpty(returnURL))
        {
            return Redirect(returnURL);
        }

        return RedirectToAction("Dashboard", "Dashboard");
    }
    else
    {
        return View(userCredential);
    }
}

我在做什么方面出错了,为什么会得到401和400?我已经检查了登录后的context.Request.Cookies["jwt"],并且存在令牌。但仍然会返回400的响应。

英文:

I am new in .NET Core so I decided to seek help here.

I am having trouble creating the Authentication Functionality of my Web Application.

The problem is, I am getting Error Response 400. and if change some of the configuration in my Program.cs like removing this line of code,

options.Events = new JwtBearerEvents
            {
                OnMessageReceived = context =&gt;
                {
                    context.Token = context.Request.Cookies[&quot;jwt&quot;];
                    return Task.CompletedTask;
                }
            };

It will return Error Response 401.

Here is my code in my Program.cs

 var builder = WebApplication.CreateBuilder(args);

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

        builder.Services.AddDbContext&lt;ApplicationDBContext&gt;(options =&gt;
        options.UseSqlServer(builder.Configuration.GetConnectionString(&quot;Dev_Environment&quot;)));

        builder.Services.AddIdentity&lt;LoginModel, IdentityRole&gt;()
                .AddEntityFrameworkStores&lt;ApplicationDBContext&gt;()
                .AddDefaultTokenProviders();

        builder.Services.AddAuthentication(options =&gt;
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(options =&gt;
        {
            options.Events = new JwtBearerEvents
            {
                OnMessageReceived = context =&gt;
                {
                    context.Token = context.Request.Cookies[&quot;jwt&quot;];
                    return Task.CompletedTask;
                }
            };
            options.SaveToken = true;
            options.RequireHttpsMetadata = false;
            options.TokenValidationParameters = new TokenValidationParameters()
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidIssuer = builder.Configuration[&quot;Hashing:ValidIssuer&quot;],
                ValidAudience = builder.Configuration[&quot;Hashing:ValidAudience&quot;],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration[&quot;Hashing:SecretKey&quot;]))
            };
        });

        builder.Services.AddAuthorization(options =&gt;
        {
            var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
                JwtBearerDefaults.AuthenticationScheme);

            defaultAuthorizationPolicyBuilder =
                defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();

            options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
        });

        var app = builder.Build();

        // Configure the HTTP request pipeline.
        if (!app.Environment.IsDevelopment())
        {
            app.UseExceptionHandler(&quot;/Home/Error&quot;);
            // 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.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();

        app.UseAuthorization();

        app.MapControllerRoute(
            name: &quot;default&quot;,
            pattern: &quot;{controller=Authentication}/{action=Login}/{id?}&quot;); 

        app.Run();

I have create a DashboardController with the Attribute [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

Here is my AuthenticationController creating a JWT Token for Authorizaiton purposes.

[HttpPost]
        public IActionResult Login(LoginModel userCredential, string returnURL)
        {
            systemLogic = new AuthenticationLogic();

            if (userCredential != null)
            {
                userCredential.Email = hasher.Encrypt(userCredential.Email);
                userCredential.Password = hasher.Encrypt(clearText: userCredential.Password);
            }

            userInput = new UserInput();

#pragma warning disable CS8604 // Possible null reference argument.
            userInput[typeof(LoginModel).FullName] = userCredential;
#pragma warning restore CS8604 // Possible null reference argument.
            systemResult = systemLogic.ExecuteProcess(configuration, userInput);

            if (systemResult.ResultCode == SystemResult.SUCCESS)
            {
                LoginModel? userInfo = systemResult[typeof(LoginModel).FullName] as LoginModel;

                Claim[] claims = new[] { new Claim(ClaimTypes.Email, hasher.Decrypt(userInfo.Email)) };

                SymmetricSecurityKey secretKey = new(Encoding.UTF8.GetBytes(configuration[&quot;Hashing:SecretKey&quot;]));

                SigningCredentials signinCredentials = new(secretKey, SecurityAlgorithms.HmacSha256);

                JwtSecurityToken tokenOptions = new(
                    issuer: configuration[&quot;Hashing:ValidIssuer&quot;],
                    audience: configuration[&quot;Hashing:ValidAudience&quot;],
                    claims: claims,
                    expires: DateTime.Now.AddHours(1),
                    signingCredentials: signinCredentials);

                string tokenString = new JwtSecurityTokenHandler().WriteToken(tokenOptions);


                // Response.Headers.Add(&quot;Authorization&quot;, &quot;Bearer &quot; + tokenString);

                Response.Cookies.Append(&quot;jwt&quot;, tokenString, new CookieOptions
                {
                    HttpOnly = true,
                    SameSite = SameSiteMode.Strict,
                    Secure = true,
                    Expires = DateTime.UtcNow.AddDays(7)
                });

                if (!string.IsNullOrEmpty(returnURL)) 
                { 
                    return Redirect(returnURL);
                }

                return RedirectToAction(&quot;Dashboard&quot;, &quot;Dashboard&quot;);
            }
            else
            { 
                return View(userCredential);
            } 
        }

What am I doing wrong on this and why I am getting 401 and 400?

I already check the context.Request.Cookies[&quot;jwt&quot;] after logging in and there is a token. And still the response will be 400.

答案1

得分: 1

我检查了您的评论,我认为400错误是由[ValidateAntiForgeryToken]属性引起的。如果您在控制器上添加了此属性,当您发送GET请求时,它也会期望一个AntiForgery令牌。根据您的要求,应该使用[AutoValidateAntiforgeryToken]来保护所有的POST端点。

您可以查看这个文档以获取更多详细信息。

英文:

I checked your comments and i think the 400 error was caused by [ValidateAntiForgeryToken] attribute .If you add the attr on the controller, when you send a get request, it would also expect an AntiForgeryToken .For your requirement,it should be [AutoValidateAntiforgeryToken] to protect all post endpoints

You could check this document related for more details

huangapple
  • 本文由 发表于 2023年2月24日 13:46:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75553016.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定