我如何在asp.net core 2.2中实现Cookie基础身份验证和jwt?

2024-04-04

我想同时使用基于 cookie 的身份验证和jwt在我的程序中,使用身份验证用户来访问mvc具有登录名和 JWT 的控制器来访问 WebApi 资源。

我尝试使用其中两个首先,我的客户端可以使用用户名和密码登录并通过 cookie 进行身份验证。第二次使用带有令牌承载的 WebApi 从应用程序访问资源,但我收到错误!

In my startup.cs我有的文件:

public void ConfigureServices(IServiceCollection services)
        {


            services.Configure<CookiePolicyOptions>(options =>
            {
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
                options.ConsentCookie.Name = "Cookie";
            });
            services.ConfigureApplicationCookie(options =>
            {
                options.Cookie.Name = "Cookie";
                options.ClaimsIssuer = Configuration["Authentication:ClaimsIssuer"];
            });

            services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");

            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));

            services.AddIdentity<ApplicationUser, ApplicationRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultUI(UIFramework.Bootstrap4)
                .AddDefaultTokenProviders();

            services.Configure<IdentityOptions>(options =>
            {
                // Password settings.
                options.Password.RequireDigit = true;
                options.Password.RequireLowercase = true;
                options.Password.RequireNonAlphanumeric = false;
                options.Password.RequireUppercase = false;
                options.Password.RequiredLength = 5;
                options.Password.RequiredUniqueChars = 1;

                // Lockout settings.
                options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
                options.Lockout.MaxFailedAccessAttempts = 5;
                options.Lockout.AllowedForNewUsers = true;

                // User settings.
                options.User.AllowedUserNameCharacters =
                "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
                options.User.RequireUniqueEmail = false;

                //Token
            });

            services.AddAuthentication(options =>
            {
                options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;

            })
                .AddCookie(options =>
                {
                    options.Cookie.Name = "Cookie";
                    options.ClaimsIssuer = Configuration["Authentication:ClaimsIssuer"];
                })
                .AddMicrosoftAccount(microsoftOptions =>
                 {
                     microsoftOptions.ClientId = Configuration["Authentication:Microsoft:ApplicationId"];
                     microsoftOptions.ClientSecret = Configuration["Authentication:Microsoft:Password"];
                 })
                .AddGoogle(googleOptions => 
                {
                    googleOptions.ClientId = "XXXXXXXXXXX.apps.googleusercontent.com";
                    googleOptions.ClientSecret = "g4GZ2#...GD5Gg1x";
                    googleOptions.Scope.Add("https://www.googleapis.com/auth/plus.login");
                    googleOptions.ClaimActions.MapJsonKey(ClaimTypes.Gender, "gender");
                    googleOptions.SaveTokens = true;
                    googleOptions.Events.OnCreatingTicket = ctx =>
                    {
                        List<AuthenticationToken> tokens = ctx.Properties.GetTokens()
                            as List<AuthenticationToken>;
                        tokens.Add(new AuthenticationToken()
                        {
                            Name = "TicketCreated",
                            Value = DateTime.UtcNow.ToString()
                        });
                        ctx.Properties.StoreTokens(tokens);
                        return Task.CompletedTask;
                    };
                })
                .AddJwtBearer(options =>
                {
                    options.ClaimsIssuer = Configuration["Authentication:ClaimsIssuer"];
                    options.SaveToken = true;
                    options.Authority = Configuration["Authentication:Authority"];
                    options.Audience = Configuration["Authentication:Audience"];
                    options.RequireHttpsMetadata = false;
                    options.TokenValidationParameters = new TokenValidationParameters()
                    {

                        ValidateIssuerSigningKey = true,

                        ValidateIssuer = true,
                        ValidIssuer = Configuration["Authentication:ValidIssuer"],

                        ValidateAudience = true,
                        ValidAudience = Configuration["Authentication:ValidAudience"],

                        ValidateLifetime = true,

                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Authentication:SecurityKey"]))
                    };
                });






            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddSession();

            services.AddSingleton<IConfiguration>(Configuration);

        }

我在这个控制器中得到了一个令牌:

[AllowAnonymous]
        [HttpPost]
        public async Task<IActionResult> GetToken(TokenLoginModel model)
        {

            if (!ModelState.IsValid) return BadRequest("Token failed to generate");
            var user = await _usermanager.FindByNameAsync(model.UserName);
            //var user = true;// (model.Password == "password" && model.Username == "username");
            if (user != null && await _usermanager.CheckPasswordAsync(user, model.Password))
            {
                var claims = new[]{
                    new Claim("ClaimsIssuer", _configuration.GetSection("Authentication:ClaimsIssuer").Value),
                new Claim(Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames.Sub,user.UserName),
                new Claim(Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString())
            };
                string SecurKey = Startup.StaticConfig.GetSection("Authentication:SecurityKey").Value;
                var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurKey));
                var token = new JwtSecurityToken(
                    issuer: _configuration.GetSection("Authentication:ValidIssuer").Value,
                    audience: _configuration.GetSection("Authentication:Audience").Value,
                    expires: DateTime.UtcNow.AddDays(30),
                    claims: claims,
                    signingCredentials: new Microsoft.IdentityModel.Tokens.SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256)
                );
                return Ok(new
                {
                    token = new JwtSecurityTokenHandler().WriteToken(token),
                    expiration = token.ValidTo
                });
            }
            return Unauthorized();

        }

我实现了创建令牌的控制,但是当我尝试使用它进行授权时,出现此错误:

An unhandled exception occurred while processing the request.

HttpRequestException: Response status code does not indicate success: 404 (Not Found).
System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()

IOException: IDX20804: Unable to retrieve document from: 'https://localhost:44383/oauth2/default/.well-known/openid-configuration'.
Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(string address, CancellationToken cancel)

InvalidOperationException: IDX20803: Unable to obtain configuration from: 'https://localhost:44383/oauth2/default/.well-known/openid-configuration'.
Microsoft.IdentityModel.Protocols.ConfigurationManager<T>.GetConfigurationAsync(CancellationToken cancel)

为了添加对 JWT 的支持,我们添加了 AddCookie 和 AddJwtBearer。让网站需要标头中的令牌将是一件令人头疼的事情,特别是对于不纯粹的 SPA 或 API 的项目。所以我真正想要的是对 Cookie 和 JWT 的支持。

在startup.cs中你有:

    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.AddDbContext<DualAuthContext>(options =>
          options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

      services.AddIdentity<ApplicationUser, IdentityRole>()
          .AddEntityFrameworkStores<DualAuthContext>()
          .AddDefaultTokenProviders();

      // Enable Dual Authentication 
      services.AddAuthentication()
        .AddCookie(cfg => cfg.SlidingExpiration = true)
        .AddJwtBearer(cfg =>
        {
          cfg.RequireHttpsMetadata = false;
          cfg.SaveToken = true;
          cfg.TokenValidationParameters = new TokenValidationParameters()
          {
            ValidIssuer = Configuration["Tokens:Issuer"],
            ValidAudience = Configuration["Tokens:Issuer"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"]))
          };
        });

      // Add application services.
      services.AddTransient<IEmailSender, EmailSender>();
      services.AddMvc();
    }

在配置方法中:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, DataSeeder seeder)
{
  ...
  app.UseAuthentication();
}

在您使用 JWT 的控制器中之后,您应该将 JWT Bearer AuthenticationSchemes 添加到 Authorize 属性,如下所示:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
  [Route("/api/customers")]
  public class ProtectedController : Controller
  {
    public ProtectedController()
    {
    }

    public IActionResult Get()
    {
      return Ok(new[] { "One", "Two", "Three" });
    }
  }

参考:ASP.NET Core 2 中的两种授权方案 https://wildermuth.com/2017/08/19/Two-AuthorizationSchemes-in-ASP-NET-Core-2

它非常简单并且使用起来很有帮助。

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

我如何在asp.net core 2.2中实现Cookie基础身份验证和jwt? 的相关文章

  • 在 C/C++ 中获得正模数的最快方法

    通常在我的内部循环中 我需要以 环绕 方式索引数组 因此 例如 如果数组大小为 100 并且我的代码要求元素 2 则应该给它元素 98 高级语言 例如 Python 可以简单地使用my array index array size 但由于某
  • 在 C# 中按元素相乘数组具有意想不到的性能

    我想找到按元素相乘两个数组的最佳方法 这是更广泛项目的一部分 其中性能而不是唯一的考虑因素 我今天开始用 C Linqpad 编写一些函数 因此它还没有以任何方式进行优化 下面代码的输出如下 Environment ProcessorCou
  • 平滑滚动.net 表单

    您好 我正在 net 中使用表单 并且在运行时动态添加大量链接标签 我将这些链接标签添加到面板并将该面板添加到 winform 当链接标签的数量增加时 表单会显示一个自动滚动条 垂直 现在 当我使用自动滚动向下滚动时 表单在滚动时不会更新其
  • EF Core 通过完全替换断开集合导航属性的更新

    使用 EF Core 5 0 我有一个 SPA 页面 可以加载Group实体及其集合Employee来自 API 的实体 var groupToUpdate await context Groups Include g gt g Emplo
  • 类特定的新删除运算符是否必须声明为静态

    标准中是否要求类特定的 new new delete 和 delete 是静态的 我可以让它们成为非静态成员运算符吗 为什么需要它们是静态的 它们被隐式声明为静态 即使您没有键入 static
  • 如何在 SqlDataReader.Read() 期间从死锁异常中恢复

    我的 NET 应用程序的事件日志显示 它在从 Sql Server 读取数据时偶尔会出现死锁 这种情况通常非常罕见 因为我们已经优化了查询以避免死锁 但有时仍然会发生 过去 我们在调用ExecuteReader函数在我们的SqlComman
  • GCC 和 ld 找不到导出的符号...但它们在那里

    我有一个 C 库和一个 C 应用程序 尝试使用从该库导出的函数和类 该库构建良好 应用程序可以编译 但无法链接 我得到的错误遵循以下形式 app source file cpp text 0x2fdb 对 lib namespace Get
  • 动态生成的控件 ID 返回为 NULL

    我可以在 Page PreInit 函数中创建动态控件 如何检索控件及其 ID 我的 C 代码用于创建动态控件之一 var btn new WebForms Button btn Text btn ID Addmore btn Click
  • fprintf() 线程安全吗?

    我正在为野人就餐问题的某些变量编写一个 C 解决方案 现在 我创建线程 每个线程都将 FILE 获取到同一个调试文件 在线程内我正在使用 fprintf 进行一些打印 打印的语句不受任何类型的互斥锁等保护 我没有在调试文件中观察到任何交错行
  • vs2008 c#:Facebook.rest.api如何使用它来获取好友列表?

    如何在此基础上取得进一步的进步 获取好友列表的下一步是什么 string APIKey ConfigurationManager AppSettings API Key string APISecret ConfigurationManag
  • 在 JSQMessagesViewController 中显示 LocationMediaItem

    我刚刚尝试实施LocationMediaItem in my Xamarin iOS应用程序使用JSQMessagesViewController 一切都很顺利 唯一的问题是UICollectionView应该显示位置的单元格永远停留在加载
  • 为什么 set_symmetry_difference 无法与比较器一起使用?

    Example program include
  • C++ php 和静态库

    我创建了一个library a 其中包含 cpp 和 h 文件 其中包含很多类 嵌套类和方法 我想在 php 示例中包含这个静态库并尝试使用它 我想提一下 我是 php 新手 我已经在 test cpp 文件中测试了我的 libray a
  • 将二进制数据从 C# 上传到 PHP

    我想将文件从 Windows C 应用程序上传到运行 PHP 的 Web 服务器 我知道 WebClient UploadFile 方法 但我希望能够分块上传文件 以便我可以监控进度并能够暂停 恢复 因此 我正在读取文件的一部分并使用 We
  • 如何通过 JsonConvert.DeserializeObject 在动态 JSON 中使用 null 条件运算符

    我正在使用 Newtonsoft 反序列化已知的 JSON 对象并从中检索一些值 如果存在 关键在于对象结构可能会不断变化 因此我使用动态来遍历结构并检索值 由于对象结构不断变化 我使用 null 条件运算符来遍历 JSON 代码看起来像这
  • 使用restsharp序列化对象并将其传递给WebApi而不是序列化列表

    我有一个看起来像的视图模型 public class StoreItemViewModel public Guid ItemId get set public List
  • 使用taskkill停止Windows服务

    我需要帮助来使用 C 终止 Windows 服务 现在要终止该服务 请使用以下选项 从命令 sc queryex ServiceName 发现后PID服务的 taskkill pid 1234 exemple f 为了便于阅读 但如果您明白
  • QFileDialog::getSaveFileName 和默认的 selectedFilter

    我有 getSaveFileName 和一些过滤器 我希望当用户打开 保存 对话框时选择其中之一 Qt 文档说明如下 可以通过将 selectedFilter 设置为所需的值来选择默认过滤器 我尝试以下变体 QString selFilte
  • 使用 QtWebEngine 将 C++ 对象暴露给 Qt 中的 Javascript

    使用 QtWebkit 可以通过以下方式将 C 对象公开给 JavascriptQWebFrame addToJavaScriptWindowObject如中所述https stackoverflow com a 20685002 5959
  • ASP.NET Core MVC 视图组件搜索路径

    在此处的文档中 https learn microsoft com en us aspnet core mvc views view components view aspnetcore 2 2 https learn microsoft

随机推荐

  • SQL Server 更新触发器,仅获取修改的字段

    我知道COLUMNS UPDATED 好吧 我需要一些快速的捷径 如果有人做了 我已经在做了 但如果有人可以节省我的时间 我会感激的 我基本上需要一个仅包含更新的列值的 XML 我需要它用于复制目的 SELECT FROM Insert 为
  • Jenkins 未识别 Maven

    我在Windows 8上安装了Tomcat 7 上面部署了Jenkins 我在 Jenkin 设置中配置了 JDK Ant 和 Maven 在 Maven 部分 我将名称命名为 LocalMaven 将 MAVEN HOME 命名为C Te
  • Postgres 正则表达式 负向前瞻

    场景 匹配除字符串 J01FA09 之外的任何以 J01 开头的字符串 我很困惑为什么以下代码不返回任何内容 SELECT 1 WHERE J01 FA09 J01FA10 当我能看到regexr com https regex101 co
  • fft 和小波

    我可以使用 fft 获取加载的 1 秒音频文件的频率 相位和幅度 并重新创建它 我现在想做的是找出每个频率在 1 秒音频文件中的开始位置和结束位置 并将数据放入数组中 示例 100hz 从 0 23 秒到 0 34 秒开始 104 34hz
  • 如何修复双编码 UTF8 字符(在 utf-8 表中)

    以前的一个LOAD DATA INFILE运行时假设 CSV 文件是latin1 编码 在此导入过程中 多字节字符被解释为两个单字符 然后 再次 使用 utf 8 进行编码 这种双重编码产生了异常 例如 代替 如何纠正这些字符串 以下 My
  • 在电子中创建多个预加载文件(每页一个)

    我正在创建我的第一个 Electron 应用程序 并且完成了表单的第一页 现在这个应用程序不是 SPA 所以我有大约 3 4 个不同的页面 并且页面通向另一个页面 为了允许正确的代码组织 我想为每个面向客户端的页面保留一个单独的预加载文件
  • 如何设置 NHibernate 事务的超时

    我需要在单个事务中完成大量数据库处理 包括使用 NHibernate 的一些处理 为了使所有内容在同一个事务中工作 我使用 NHibernate 的 Session 来启动它 并在其中登记其他工作的命令 一切都很顺利 直到我承诺为止 那时我
  • 停止无限循环中的delphi程序

    当 Delphi 中发生无限循环时 当我按下停止按钮时 调试器甚至不会给我堆栈跟踪 如果我怀疑程序在哪里停止 我可以放置一个断点 如果这是正确的无限循环 它将停止 下面是一个故意造成无限循环的示例程序 procedure TForm1 bt
  • Android 中的最大 BackStack 大小

    我是android开发的新手 我需要知道最大内存大小 of 后台堆栈 in android我想知道有多少活动 of 安卓应用 can be 存储在 BackStack 中 Thanks 后台堆栈的最大内存大小与设备上的可用内存量相同 您可以
  • 有 F#(或 C#)中的 R 树实现吗? [复制]

    这个问题在这里已经有答案了 可能的重复 是否有任何记录在案的 NET 的免费 R Tree 实现 https stackoverflow com questions 2041834 is there any documented free
  • 多行组并使用正则表达式进行搜索

    好的 正则表达式向导 我希望能够搜索我的日志文件并找到其中包含 错误 一词的任何会话 然后返回整个会话日志条目 我知道我可以使用字符串 数组来做到这一点 但我想学习如何使用正则表达式来做到这一点 但这就是问题 如果我决定使用正则表达式来做到
  • DataTables 固定标题与宽表中的列未对齐

    Problem 当使用sScrollX sScrollXInner and or sScrollY为了实现内部内容滚动的固定标题表格 在 Chrome 和 IE 中 表格的标题与正文的其余部分不对齐 另一方面 Firefox 可以完美地显示
  • 为什么堆比二叉树更好地表示优先级队列?

    在 最大 堆中 很容易找到最大的项目O 1 时间 但要真正删除它 你需要复杂性O log n 因此 如果从堆中插入和删除都是O log n 用堆来表示优先级队列比二叉树有什么优点 堆使用较少的内存 它们可以作为数组实现 因此没有存储指针的开
  • OpenFileDialog 切断预先填充的文件名[重复]

    这个问题在这里已经有答案了 我使用以下命令来显示 打开文件 对话框 OpenFileDialog fdlg new OpenFileDialog fdlg FileName Properties Settings Default Last
  • 如何使用 webpack 填充 Promise?

    我正在使用 webpack 来捆绑我的 JavaScript 我依赖于类似的模块popsicle https www npmjs com package popsicle哪个使用任何承诺 https www npmjs com packag
  • [ngModel] 和 (ngModelChange) 如何协同工作?

    我是 Angular 的新手 正在学习 Angular 6 我了解 ngModel 但当我尝试 ngModelChange 时 出现了一些问题 我有一个 html 元素 超文本标记语言
  • 在 heroku 上以沙箱模式运行 Rails 控制台

    在文档中找不到它 在SO上也找不到它 但是有没有办法在heroku Celadon Cedar 上以沙盒模式运行Rails 3 2 x 控制台 相当于 rails console sandbox 对于更 Heroku 方式 的替代方案 he
  • 使用 JQuery 和 Django 上传图像

    在继续阅读之前 请相信我 我已经阅读了有关此主题的所有其他帖子 但没有一个对您有帮助 我正在尝试向我的网站添加图像上传功能 我想上传图片 通过 ajax 帖子 我无法让这个工作 这是我所拥有的 HTML 我有一个特殊的设置 以便显示图像而不
  • 屏幕截图安全桌面

    我正在处理屏幕共享项目 我正在使用以下功能捕获桌面屏幕 它工作正常 但每当安全桌面提示提升 https learn microsoft com en us windows security threat protection securit
  • 我如何在asp.net core 2.2中实现Cookie基础身份验证和jwt?

    我想同时使用基于 cookie 的身份验证和jwt在我的程序中 使用身份验证用户来访问mvc具有登录名和 JWT 的控制器来访问 WebApi 资源 我尝试使用其中两个首先 我的客户端可以使用用户名和密码登录并通过 cookie 进行身份验