ASP.NET Core 5.0 JWT 身份验证抛出 401 代码 [重复]

2023-11-29

我有一个使用 JWT 身份验证的 ASP.NET Core 5.0 API。

目前我想要它做的就是读取按钮中的令牌

@Html.ActionLink("Test","Oper","Home")

这是[Authorize]标题并根据我的标准验证它们。我不知道错过了什么,但它总是返回 HTTP 401 代码。

测试添加此代码

app.UseCors(x => x.AllowAnyHeader()
                  .AllowAnyMethod()
                  .WithOrigins("https://localhost:4200"));

Error:

System.InvalidOperationException:CORS 协议不允许同时指定通配符(任何)来源和凭据。如果需要支持凭据,请通过列出各个来源来配置 CORS 策略。

与终端 pty 主机进程的连接无响应,终端可能停止工作

这不是一个 Angular 项目。

This is Startup.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.FileProviders;
using System.IO;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;

namespace JWTtokenMVC
{
    public class Startup
    {
        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)
        {
            services.AddControllersWithViews();
            services.AddCors(options =>
            {
                options.AddPolicy("CorsPolicy", builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials().Build());
            });

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.IncludeErrorDetails = true;
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType ="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
                    RoleClaimType ="http://schemas.microsoft.com/ws/2008/06/identity/claims/role",
                    ValidateIssuer = true,
                    ValidateAudience = false,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = Configuration["Jwt:Issuer"],
                    ValidAudience = Configuration["Jwt:Issuer"],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])

                    )
                };
            });
        }

        // 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();
            }
            else
            {
                app.UseExceptionHandler("/Home/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.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseStaticFiles(new StaticFileOptions
            {
                FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "Test_modules")),
                RequestPath = "/" + "Test_modules"
            });
            app.UseCookiePolicy();

            app.UseRouting();

            app.UseAuthentication();

            app.UseAuthorization();
            app.UseCors(x => x.AllowAnyHeader()
                              .AllowAnyMethod()
                              .WithOrigins("https://localhost:4200"));

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

This is HomeController.cs- 登录获取 Jwt 令牌即可:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using JWTtokenMVC.Models;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Microsoft.Extensions.Configuration;
using JWTtokenMVC.Models.Test;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;

namespace JWTtokenMVC.Controllers
{
    public class HomeController : Controller
    {
        private IConfiguration _config;

        public HomeController(IConfiguration config)
        {
            _config = config;
        }

        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }

        private string GenerateJSONWebToken(UserPaul userinfo)
        {
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
            var claims = new[]
            {
                new Claim(JwtRegisteredClaimNames.Sub,userinfo.Username),
                new Claim(JwtRegisteredClaimNames.Email,userinfo.Email),
                new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString()),
            };
            var token = new JwtSecurityToken(
                issuer: _config["Jwt:Issuer"],
                audience: _config["Jwt:Issuer"],
                claims,
                expires: DateTime.Now.AddMinutes(10),
                signingCredentials: credentials
                );
            var encodetoken = new JwtSecurityTokenHandler().WriteToken(token);

            var cookieOptions = new CookieOptions();
            //cookieOptions.Expires = DateTimeOffset.UtcNow.AddHours(12);//you can set this to a suitable timeframe for your situation
            cookieOptions.HttpOnly = true;
            cookieOptions.Expires = DateTime.Now.AddMinutes(1);
            //cookieOptions.Domain = Request.Host.Value;
            cookieOptions.Path = "/";
            Response.Cookies.Append("jwt", encodetoken, cookieOptions);

            return encodetoken;
        }

        [HttpPost]
        public IActionResult Login()
        {
            string AccountNumber="TestUser";
            JWTtokenMVC.Models.TestContext userQuery = new JWTtokenMVC.Models.TestContext();
            var query = userQuery.Testxxxx.Where(N => N.UserId ==AccountNumber).FirstOrDefault();
            IActionResult response = Unauthorized();

            if (query != null)
            {
                var tokenStr = GenerateJSONWebToken(query);
                response = Ok(new { token = tokenStr });
            }

            return response;
        }

        [Authorize]
        [HttpGet("Home/Oper")]
        public IActionResult Oper()
        {
            var authenticationCookieName = "jwt";
            var cookie = HttpContext.Request.Cookies[authenticationCookieName];
            List<Test_SHOW> sHOWs = new List<Test_SHOW>();
            JWTtokenMVC.Models.Test.TestContext userQuery= new JWTtokenMVC.Models.Test.TestContext();
            var query = userQuery.Test.Select(T => new Test_SHOW
            {
                number= T.number,
                name= T.name,
                mail= T.mail

            }).OrderBy(o => o.Iid);

            sHOWs.AddRange(query);

            return View("Views/Home/Oper.cshtml", sHOWs);
        }
    }
}

This is Test.cshtml:

@{
    ViewBag.Title = "Home Page";
}

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions{
    public string GetAntiXsrfRequestToken()
    {
        return Xsrf.GetAndStoreTokens(Context).RequestToken;
    }
}

<input type="hidden" id="RequestVerificationToken"
       name="RequestVerificationToken" value="@GetAntiXsrfRequestToken()">


<form method="post" asp-antiforgery="false">
<!--form -->


    <div>
        <span style="color:red">@ViewBag.Msg</span>
    </div>

    <div class="col-md-4 select-outline">
</div>
    <button type="button" class="btn btn-light">@Html.ActionLink("Test","Oper","Home")</button>
  <button type="button" class="btn btn-light">@Html.ActionLink("TestLogin","Login","Home")</button>

</form>

最后这是Oper.cshtml:

@using JWTtokenMVC.Models.Test
@model List<Test_SHOW>

@{
    ViewBag.Title = "test";
}

<h2>Test List</h2>

<table class="table table-hover">
    <tr>
        <th>
          number
        </th>
        <th>
           name
        </th>
        <th>
            mail
        </th>
    </tr>
    @foreach (var item in Model)
    {    
        <tr>
             <td>
                @Html.DisplayFor(modelItem => item.number)
            </td>
            <td>
                <span class='text-danger'>@Html.DisplayFor(modelItem => item.name)</span>
            </td>
            <td>
                  <span class='text-danger'>@Html.DisplayFor(modelItem => item.mail)</span>
            </td>
        </tr>
    }
</table>

这是我的appsettings.json file:

{
  "Logging": {
    "LogLevel": {
      "Default": "TestInformation",
      "Microsoft": "TestWarning",
      "Microsoft.Hosting.Lifetime": "TestInformation"
    }
  },
  "AllowedHosts": "*",
  "Jwt": {
    "Key": "TestProdigy",
    "Issuer": "Test.mail.com"
  }
}

@Patriom Sarkar 的回答解决了您的 CORS 问题/错误

关于您的 401 未经授权的回复

这些可能与 CORS 无关。

您在这里遇到的问题是您已将 JwtBearer JSON Web 令牌配置为存在于您的请求中Authorize端点。默认情况下,它将使用授权请求标头中存在的承载令牌。

这意味着,为了导航/呼叫Oper(),您需要确保“Authorization: Bearer {token}”存在并具有有效的令牌(作为请求标头)。

目前,在您的Login处理,您正在生成令牌并执行Set-Cookie以便用户代理/客户端使用令牌作为值创建“jwt”cookie;但是,用户代理不会自动将该 jwt cookie 作为授权:承载令牌添加到后续请求的标头中。所以JwtBearer配置开启Authorize归因端点将无效。

另外值得注意的是,在 Xhr 或 Fetch 操作中设置标头在 SPA 框架中是受支持且正常的(包括 Cookie 存储的 jwt_tokens)。但是,您在这里不是执行 Xhr 或 Fetch 请求,而是执行 html 表单发布工作流程/机制 - 导航页面/视图。在这方面,在客户端设置授权标头(AFAIK)是不可能的。

要支持此处的页面/视图导航,您需要在服务器端实现一个解决方案,该解决方案使用传递的令牌设置令牌jwt cookie.

该解决方案包含在在 ASP.NET Core 中从 Cookie 而不是 headers 读取 JWT 令牌作者:@柯克·拉金

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

此外

context.Token总是null或在此范围内为空。此声明和赋值不会发生预处理或后处理。如果您打算支持授权标头和 Cookie,则应在此实现该条件OnMessageReceived指定的代表。

您可以查看默认处理GitHub 上的 JwtBearerHandler (aspnetcore 5.0).

再次感谢@Kirk Larkin 在链接问题的回复评论中提供了这些附加信息。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ASP.NET Core 5.0 JWT 身份验证抛出 401 代码 [重复] 的相关文章

  • c# - 显示小数点到小数点后 6 位 [重复]

    这个问题在这里已经有答案了 可能的重复 具有 N 个小数位的 Double ToString https stackoverflow com questions 3059759 double tostring with n number o
  • 如果两个线程同时访问同一个 bool 变量会发生什么?

    我有一个跨平台 C 程序 其中使用 boost 库创建异步计时器 我有一个全局变量 bool receivedInput false 一个线程等待并处理输入 string argStr while 1 getline cin argStr
  • 为什么这个 oracle 批量插入不起作用?

    我正在尝试将一些数据批量插入到 oracle 数据库中 我按照文档中的示例进行操作 this DataBaseAccess new OracleConnection connString var dataAdapter new Oracle
  • WPF Dispatchertimer 延迟反应/冻结

    在我的 WPF 应用程序中 我使用 3 个不同的 DispatcherTimers 一种是用于显示当前时间 一种是每 5 秒运行一次数据库查询 第三个每 1 秒刷新一次自定义按钮的值 当我的程序运行时 有很多延迟 冻结 例如 时间开始正确计
  • std::tr1::function 和 std::tr1::bind

    我在使用时遇到问题veryC 类中的复杂 C 函数 重写 C 函数是not一个选项 C函数 typedef void integrand unsigned ndim const double x void fdata unsigned fd
  • 试图使用加密来混淆我的项目打破了它

    我试图尝试不同的混淆选项 为了做到这一点 我首先尝试了加密货币 以下是我遵循的步骤 打开加密向导并选择一些选项 选择我的解决方案文件 完成向导后 我看到有些 Dll 被很好地混淆了 但我的项目现在无法构建 我注意到的两件事是 我的文件夹中有
  • 为什么 httpRuntime targetFramework="4.5" 禁止抓取 .ASPXAUTH cookie?

    当我的 web config 具有以下 httpRuntime 时 我的控制器无法获取 cookie ASPXAUTH 它似乎能够获取任何其他 cookie 无论带或不带句点前缀 如果我删除下面的行 它就可以正常工作
  • 为什么我无法调试动态加载的程序集?

    我正在开发一个 Web API 项目 该项目使用内部模拟框架 允许拦截和修改来自控制器的响应 它使用 MEF 加载包含某些先决条件匹配时执行的代码的程序集 我知道这是正常工作的 因为我可以在响应中看到模拟已被执行 但由于某种原因我无法调试动
  • 我可以对(非成员)函数使用部分模板特化吗?

    我试图在 非成员 函数上使用部分模板专业化 但我在语法上遇到了问题 我在 StackOverflow 中搜索了其他部分模板专业化问题 但这些问题涉及类或成员函数模板的部分专业化 作为起点 我有 struct RGBA RGBA uint8
  • Request.Form 和 Request.QueryString 之间的区别?

    有人可以告诉我两者之间的确切区别吗Request Form and Request QueryString 我知道一个区别 比如 如果HTTP请求方式为POST 则用户提交的数据在申请表 收藏 如果HTTP请求方法是GET 则用户提交的数据
  • 为什么未到达的 try-catch 块会增加运行时间?

    我目前正在创建自己的容器库 但我已经看到无法访问 if 语句无效 try catch阻止增加运行时间 这是我的测试 Vector cpp template
  • 为什么必须通过 this 指针访问模板基类成员?

    如果下面的类不是模板 我可以简单地拥有x in the derived班级 但是 通过下面的代码 我have to use this gt x Why template
  • #define 内存地址声明

    这个 define 语句有什么作用 它用于定义内存地址 但我不明白 uint32 t 部分 define GPxDAT uint32 t 0x6FC0 通常用于访问映射到地址空间的硬件寄存器 或者一些特定的内存地址 硬件寄存器应定义为vol
  • 如何组合||条件语句中的运算符[重复]

    这个问题在这里已经有答案了 代替 if foo 1 foo 5 foo 9 我喜欢将它们组合起来 类似于以下内容 这不起作用 if foo 1 5 9 那可能吗 不幸的是不是 你最好的选择是创建一个扩展方法 public static bo
  • 如何创建和使用类箭头运算符? [复制]

    这个问题在这里已经有答案了 因此 在到处研究之后 我似乎找不到如何创建类箭头运算符 即 class Someclass operator gt 我只需要知道如何使用它并正确使用它 它的输入是什么 它返回什么 我如何正确地声明 原型化它 运算
  • 返回 ICollection 而不是 List 的真正优势是什么? [复制]

    这个问题在这里已经有答案了 我读过几篇博客文章 提到对于公共 API 我们应该始终返回 ICollection 或 IEnumerable 而不是 List 返回 ICollection 而不是 List 的真正优势是什么 Thanks 复
  • 在Framework 4.6项目中使用.net core DLL

    我已经在 net core 2 0 中构建了一个 DLL 现在我想在使用 net 4 6 1 框架的 WinForms 项目中使用它 我可以引用该 dll 但收到 System IO FileLoadException 表示找不到 Syst
  • 是否可以编写一个在另一个 Windows 应用程序中选择文本时收到通知的 Windows 应用程序?

    我很好奇是否可以编写一个程序来监视我的文本选择 一种可能的用途是编写一个与编辑器 IDE 无关的代码格式化程序 应用程序 服务 P 启动并以某种方式挂接到窗口中 以便在任何窗口中选择文本时收到通知 启动其他一些应用程序 A 用户选择 A 中
  • asp.net mvc GET 请求上的 formcollection 应该为空

    我正在发布一个简单的操作 public void Login FormCollection formCollection 即使查询字符串值很少 formcollection Count is 0 是靠行为吗 FormCollection 使
  • DataGridView 捕获用户行选择

    我在处理选择时遇到问题DataGridView 我的网格视图包含一个金额列 表单上有一个文本框 应显示所选网格视图行的总数 因此 我需要在用户选择 取消选择 gridview 行时捕获事件并相应地计算 添加 减去 金额 我找到了两种方法 使

随机推荐