如何为 .NET Core Web API 进行安全身份验证?

Posted

技术标签:

【中文标题】如何为 .NET Core Web API 进行安全身份验证?【英文标题】:How to make secure authentication for .NET Core Web API? 【发布时间】:2020-11-15 14:47:57 【问题描述】:

我正在使用 .NET Core Web API、Entity Framework 和 React 开发一个应用程序。我最近一直在阅读很多关于我的 API 可能的身份验证技术的文章,我发现普通 JWT 并不完全安全,所以起初我决定将 OpenID Connect 与 IdentityServer 4 一起使用。我了解 OAuth 2.0 和 OpenID 背后的想法Connect 是在登录过程中隐藏用户凭据,并让外部身份验证提供商参与发布访问令牌,但我不想依赖此类服务,因为并非每个人都在 Facebook 等上拥有帐户。我认为这是一种可选方式登录。我想让用户只需登录名和密码即可登录。那么在现代网络应用中实现这一目标的最佳(安全)方式是什么?

将项目 1 作为客户端应用程序,将项目 2 作为 API 资源,将项目 3 作为授权服务 (IdentityServer4),我考虑以下场景:

    用户可以在授权服务上创建一个帐户,该帐户负责颁发通过客户端应用程序访问 API 资源所需的令牌。授权服务仅注册为我的客户端应用程序的授权提供者。

    使用资源所有者密码授权从授权服务获取授权令牌 - 规范不推荐使用此令牌,但在我的情况下,因为用户必须向授权服务提供凭据,并且我将托管每个项目,我看不到任何问题.

    不用担心 OAuth 并使用 ASP.NET Core Identity + Bearer token 身份验证来实现授权机制。

高度赞赏的任何想法或建议。

【问题讨论】:

也许我的回答here 有用。 【参考方案1】:

我使用 JwtBearer 包,将其连接到您的 Startup.cs 配置方法中,例如

                .UseJwtBearerAuthentication(new JwtBearerOptions
                
                    AutomaticAuthenticate = true,
                    AutomaticChallenge = true,
                    TokenValidationParameters = new TokenValidationParameters
                    
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration["AppSettings:AuthConfig:SecretKey"])),
                        ValidateIssuer = true,
                        ValidIssuer = Configuration["AppSettings:AuthConfig:Issuer"],

                        ValidateAudience = true,
                        ValidAudience = Configuration["AppSettings:AuthConfig:Audience"],

                        ValidateLifetime = true,
                    
                )

我的用户控制器上的登录操作看起来像

        [HttpPost]
        public string Post([FromBody]LoginRequest request)
        
            var contact = dbContext.Contacts.Where(c => c.Active && c.Email == request.Email).Select(c => new  c.Id, c.PasswordHash ).SingleOrDefault();

            if (contact == null || !Security.PasswordHash.ValidatePassword(request.Password, contact.PasswordHash))
            
                return string.Empty;
            

            var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(appSettings.AuthConfig.SecretKey));

            var now = DateTime.UtcNow;

            var claims = new Claim[]
            
                new Claim(JwtRegisteredClaimNames.Sub, contact.Id.ToString()),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.Now.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64)
            ;

            var jwt = new JwtSecurityToken(
                issuer: appSettings.AuthConfig.Issuer,
                audience: appSettings.AuthConfig.Audience,
                claims: claims,
                notBefore: now,
                expires: now.AddDays(30),
                signingCredentials: new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256));

            jwt.Payload.Add("roles", dbContext.ContactRoles.Where(cr => cr.ContactId == contact.Id).Select(ur => ur.Role.Name).ToArray());

            return new JwtSecurityTokenHandler().WriteToken(jwt);
        

我在客户端为 Angular 使用 JWT 包,React 可能有类似的东西。

【讨论】:

以上是关于如何为 .NET Core Web API 进行安全身份验证?的主要内容,如果未能解决你的问题,请参考以下文章

如何为 dotnet core(web Api) 代码更改以及 TypeScript 代码更改启用实时重新加载

.使用 Mongodb 进行 Net Core Web Api 身份验证

如何为 .NET Core 3.0 中 WPF 配置依赖注入 ?

MediatR CQRS - 如何处理不存在的资源(asp.net core web api)

如何为 .NET Core 重命名 ABP 中的列?

如何为 Kestrel 主机添加 NTLM 支持?