c# - DB-First 身份验证与 ASP.NET Web API 2 + EF6 混淆

标签 c# asp.net entity-framework asp.net-web-api2 ef-database-first

我需要为现有的 MySQL 数据库创建 Web API C# 应用程序。我已经设法使用 Entity Framework 6 将每个数据库表绑定(bind)到 RESTful API (允许 CRUD 操作)

我想实现一个登录/注册系统(以便我可以在未来实现角色和权限,并限制某些 API 请求)

我必须使用的 MySQL 数据库有一个用户表 (称为 user),它具有以下不言自明的列:

  • id
  • 电子邮件
  • 用户名
  • password_hash

似乎身份验证的事实标准是 ASP.Net Identity。我花了最后一个小时试图弄清楚如何使 Identity 与现有的 DB-First Entity Framework 设置一起工作。

如果我尝试构造 ApplicationUser 实例来存储 user 实例(来自 MySQL 数据库的实体) 来检索用户数据,我得到以下结果错误:

The entity type ApplicationUser is not part of the model for the current context.

我假设我需要将身份数据存储在我的 MySQL 数据库中,但找不到任何关于如何做到这一点的资源。我已经尝试完全删除 ApplicationUser 类并使我的 user 实体类派生自 IdentityUser,但调用 UserManager.CreateAsync 导致 LINQ to Entities 转换错误。

如何在具有现有 user 实体的 Web API 2 应用程序中设置身份验证?

最佳答案

你说:

I want to implement a login/registration system (so that I can implement roles and permissions in the future, and restrict certain API requests).

How do I setup authentication in a Web API 2 application, having an existing user entity?

这绝对意味着您不需要需要 ASP.NET Identity。 ASP.NET Identity 是一种处理所有用户信息的技术。它实际上并没有“制定”身份验证机制。 ASP.NET Identity 使用 OWIN 身份验证机制,这是另一回事。

您要查找的不是“如何将 ASP.NET Identity 与我现有的用户表一起使用”,而是“如何使用我现有的用户表配置 OWIN 身份验证”

要使用 OWIN Auth,请按照以下步骤操作:

安装包:

Owin
Microsoft.AspNet.Cors
Microsoft.AspNet.WebApi.Client
Microsoft.AspNet.WebApi.Core
Microsoft.AspNet.WebApi.Owin
Microsoft.AspNet.WebApi.WebHost
Microsoft.Owin
Microsoft.Owin.Cors
Microsoft.Owin.Host.SystemWeb
Microsoft.Owin.Security
Microsoft.Owin.Security.OAuth

创建 Startup.cs根文件夹中的文件(示例):

确保 [assembly: OwinStartup] 已正确配置

[assembly: OwinStartup(typeof(YourProject.Startup))]
namespace YourProject
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var config = new HttpConfiguration();
            //other configurations

            ConfigureOAuth(app);
            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
            app.UseWebApi(config);
        }

        public void ConfigureOAuth(IAppBuilder app)
        {
            var oAuthServerOptions = new OAuthAuthorizationServerOptions()
            {
                AllowInsecureHttp = true,
                TokenEndpointPath = new PathString("/api/security/token"),
                AccessTokenExpireTimeSpan = TimeSpan.FromHours(2),
                Provider = new AuthorizationServerProvider()
            };

            app.UseOAuthAuthorizationServer(oAuthServerOptions);
            app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
        }
    }

    public class AuthorizationServerProvider : OAuthAuthorizationServerProvider
    {
        public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            context.Validated();
        }

        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
            context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

            try
            {
                //retrieve your user from database. ex:
                var user = await userService.Authenticate(context.UserName, context.Password);

                var identity = new ClaimsIdentity(context.Options.AuthenticationType);

                identity.AddClaim(new Claim(ClaimTypes.Name, user.Name));
                identity.AddClaim(new Claim(ClaimTypes.Email, user.Email));

                //roles example
                var rolesTechnicalNamesUser = new List<string>();

                if (user.Roles != null)
                {
                    rolesTechnicalNamesUser = user.Roles.Select(x => x.TechnicalName).ToList();

                    foreach (var role in user.Roles)
                        identity.AddClaim(new Claim(ClaimTypes.Role, role.TechnicalName));
                }

                var principal = new GenericPrincipal(identity, rolesTechnicalNamesUser.ToArray());

                Thread.CurrentPrincipal = principal;

                context.Validated(identity);
            }
            catch (Exception ex)
            {
                context.SetError("invalid_grant", "message");
            }
        }
    }
}

使用 [Authorize]属性来授权操作。

调用api/security/tokenGrantType , UserName , 和 Password获取不记名 token 。像这样:

"grant_type=password&username=" + username + "&password=" password;

HttpHeader Authorization 内发送 token 作为Bearer "YOURTOKENHERE" .像这样:

headers: { 'Authorization': 'Bearer ' + token }

希望对您有所帮助!

关于c# - DB-First 身份验证与 ASP.NET Web API 2 + EF6 混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33398961/

相关文章:

c# - 填充可为空的小数时,小数会四舍五入,为什么?

c# - 如何使用asp和C#下载多个文件

entity-framework - 提高 Entity Framework 中的批量插入性能

entity-framework - 必须存在默认的 DbContext 上下文,或者必须提供上下文工厂

c# - 在 MySQL 和 Entity Framework 中删除评论及其所有子项的 SQL 查询

c# - StackExchange.Redis 空闲时间后出现连接问题

c# - 无法从代码更改 SiteCore 8.0(更新 3)中的 mvc 布局

c# - 排除字符串开头和结尾的特殊字符

asp.net - 找不到 ASP.net 用户控件的命名空间名称

c# - 单击 HTML 按钮调用服务器端功能