将 ASP.NET MVC5 身份验证添加到现有项目
Posted
技术标签:
【中文标题】将 ASP.NET MVC5 身份验证添加到现有项目【英文标题】:Adding ASP.NET MVC5 Identity Authentication to an existing project 【发布时间】:2015-11-04 18:43:36 【问题描述】:我在网上看到过很多类似的页面,但大多数都使用新项目而不是现有项目,或者没有必要的功能。因此,我有一个现有的 MVC 5
项目,并希望将 ASP.NET MVC5 Identity 与登录、电子邮件确认和密码重置功能集成。
除此之外,我还需要在数据库上创建所有必要的表,即用户、角色、组等(我在项目中使用 EF Code First)。有没有符合这些需求的文章或样本?
【问题讨论】:
这是一个多么棒的问题,下面给出了多么简单的解决方案。我喜欢它通读,也非常需要集成到我现有的项目中。 【参考方案1】:为现有项目配置身份并不难。您必须安装一些 NuGet 包并进行一些小配置。
首先使用包管理器控制台安装这些 NuGet 包:
PM> Install-Package Microsoft.AspNet.Identity.Owin
PM> Install-Package Microsoft.AspNet.Identity.EntityFramework
PM> Install-Package Microsoft.Owin.Host.SystemWeb
添加一个用户类和IdentityUser
继承:
public class AppUser : IdentityUser
//add your custom properties which have not included in IdentityUser before
public string MyExtraProperty get; set;
为角色做同样的事情:
public class AppRole : IdentityRole
public AppRole() : base()
public AppRole(string name) : base(name)
// extra properties here
将您的 DbContext
父级从 DbContext
更改为 IdentityDbContext<AppUser>
,如下所示:
public class MyDbContext : IdentityDbContext<AppUser>
// Other part of codes still same
// You don't need to add AppUser and AppRole
// since automatically added by inheriting form IdentityDbContext<AppUser>
如果您使用相同的连接字符串并启用迁移,EF 将为您创建必要的表。
或者,您可以扩展 UserManager
以添加您想要的配置和自定义:
public class AppUserManager : UserManager<AppUser>
public AppUserManager(IUserStore<AppUser> store)
: base(store)
// this method is called by Owin therefore this is the best place to configure your User Manager
public static AppUserManager Create(
IdentityFactoryOptions<AppUserManager> options, IOwinContext context)
var manager = new AppUserManager(
new UserStore<AppUser>(context.Get<MyDbContext>()));
// optionally configure your manager
// ...
return manager;
由于 Identity 是基于 OWIN 的,所以你也需要配置 OWIN:
将类添加到App_Start
文件夹(或其他任何地方,如果您愿意)。此类由 OWIN 使用。这将是你的创业课程。
namespace MyAppNamespace
public class IdentityConfig
public void Configuration(IAppBuilder app)
app.CreatePerOwinContext(() => new MyDbContext());
app.CreatePerOwinContext<AppUserManager>(AppUserManager.Create);
app.CreatePerOwinContext<RoleManager<AppRole>>((options, context) =>
new RoleManager<AppRole>(
new RoleStore<AppRole>(context.Get<MyDbContext>())));
app.UseCookieAuthentication(new CookieAuthenticationOptions
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Home/Login"),
);
几乎完成了,只需将这行代码添加到您的web.config
文件中,以便 OWIN 可以找到您的启动类。
<appSettings>
<!-- other setting here -->
<add key="owin:AppStartup" value="MyAppNamespace.IdentityConfig" />
</appSettings>
现在在整个项目中,您可以像使用 VS 已安装的任何新项目一样使用 Identity。以登录操作为例
[HttpPost]
public ActionResult Login(LoginViewModel login)
if (ModelState.IsValid)
var userManager = HttpContext.GetOwinContext().GetUserManager<AppUserManager>();
var authManager = HttpContext.GetOwinContext().Authentication;
AppUser user = userManager.Find(login.UserName, login.Password);
if (user != null)
var ident = userManager.CreateIdentity(user,
DefaultAuthenticationTypes.ApplicationCookie);
//use the instance that has been created.
authManager.SignIn(
new AuthenticationProperties IsPersistent = false , ident);
return Redirect(login.ReturnUrl ?? Url.Action("Index", "Home"));
ModelState.AddModelError("", "Invalid username or password");
return View(login);
您可以创建角色并添加到您的用户:
public ActionResult CreateRole(string roleName)
var roleManager=HttpContext.GetOwinContext().GetUserManager<RoleManager<AppRole>>();
if (!roleManager.RoleExists(roleName))
roleManager.Create(new AppRole(roleName));
// rest of code
您还可以向用户添加角色,如下所示:
UserManager.AddToRole(UserManager.FindByName("username").Id, "roleName");
通过使用Authorize
,您可以保护您的操作或控制器:
[Authorize]
public ActionResult MySecretAction()
或
[Authorize(Roles = "Admin")]]
public ActionResult MySecretAction()
您还可以安装其他软件包并对其进行配置以满足您的要求,例如 Microsoft.Owin.Security.Facebook
或任何您想要的。
注意:不要忘记将相关的命名空间添加到您的文件中:
using Microsoft.AspNet.Identity;
using Microsoft.Owin.Security;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Owin;
您还可以查看我的其他答案,例如 this 和 this 以了解身份的高级使用。
【讨论】:
两种解决方案看起来相似。我使用AppRole
和Identity 的角色管理器对用户进行分类。由于 Role
s 和 RoleManager
已经由 Identity 本身实现,您不需要重写已经实现的代码。我将更新帖子以向您展示如何使用角色。正如我之前所说,您只需要添加AppUser
和AppRole
实体来初始化身份。通过从IdentityDbContext<AppUser>
继承您的DbContext
,所有必要的表都可以添加您的表。您无需执行任何操作,只需启用迁移即可。
我刚刚添加了一些示例用法。将Microsoft.AspNet.Identity.EntityFramework
安装到您的域和其他用户界面。
1) 不要担心您的web.config
。不要更换旧的。 Read this for more info。我认为您的 MVC 也升级了。
我刚刚阅读了你留下的所有帮助克林特伊斯特伍德的 cmets,干得好!世界需要更多像 You plusOne 这样的人
几乎成功了。但是我在迁移过程中遇到了错误EntityType 'IdentityUserRole' has no key defined
,我通过将base.OnModelCreating(modelBuilder);
添加到OnModelCreating
函数来解决它。【参考方案2】:
这就是我将 Identity 与现有数据库集成的方法。
使用 MVC 模板创建示例 MVC 项目。这包含了 Identity 实现所需的所有代码 - Startup.Auth.cs、IdentityConfig.cs、Account Controller 代码、Manage Controller、Models 和相关视图。
为 Identity 和 OWIN 安装必要的 nuget 包。通过查看示例项目中的参考资料和@Sam 的答案,您会有所了解
将所有这些代码复制到您现有的项目中。请注意不要忘记为 Identity 添加“DefaultConnection”连接字符串以映射到您的数据库。请检查 IdentityModel.cs 中的 ApplicationDBContext 类,您将在其中找到对“DefaultConnection”连接字符串的引用。
这是我在现有数据库上运行以创建必要表的 SQL 脚本:
USE ["YourDatabse"]
GO
/****** Object: Table [dbo].[AspNetRoles] Script Date: 16-Aug-15 6:52:25 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetRoles](
[Id] [nvarchar](128) NOT NULL,
[Name] [nvarchar](256) NOT NULL,
CONSTRAINT [PK_dbo.AspNetRoles] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[AspNetUserClaims] Script Date: 16-Aug-15 6:52:25 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetUserClaims](
[Id] [int] IDENTITY(1,1) NOT NULL,
[UserId] [nvarchar](128) NOT NULL,
[ClaimType] [nvarchar](max) NULL,
[ClaimValue] [nvarchar](max) NULL,
CONSTRAINT [PK_dbo.AspNetUserClaims] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
/****** Object: Table [dbo].[AspNetUserLogins] Script Date: 16-Aug-15 6:52:25 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetUserLogins](
[LoginProvider] [nvarchar](128) NOT NULL,
[ProviderKey] [nvarchar](128) NOT NULL,
[UserId] [nvarchar](128) NOT NULL,
CONSTRAINT [PK_dbo.AspNetUserLogins] PRIMARY KEY CLUSTERED
(
[LoginProvider] ASC,
[ProviderKey] ASC,
[UserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[AspNetUserRoles] Script Date: 16-Aug-15 6:52:25 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetUserRoles](
[UserId] [nvarchar](128) NOT NULL,
[RoleId] [nvarchar](128) NOT NULL,
CONSTRAINT [PK_dbo.AspNetUserRoles] PRIMARY KEY CLUSTERED
(
[UserId] ASC,
[RoleId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[AspNetUsers] Script Date: 16-Aug-15 6:52:25 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetUsers](
[Id] [nvarchar](128) NOT NULL,
[Email] [nvarchar](256) NULL,
[EmailConfirmed] [bit] NOT NULL,
[PasswordHash] [nvarchar](max) NULL,
[SecurityStamp] [nvarchar](max) NULL,
[PhoneNumber] [nvarchar](max) NULL,
[PhoneNumberConfirmed] [bit] NOT NULL,
[TwoFactorEnabled] [bit] NOT NULL,
[LockoutEndDateUtc] [datetime] NULL,
[LockoutEnabled] [bit] NOT NULL,
[AccessFailedCount] [int] NOT NULL,
[UserName] [nvarchar](256) NOT NULL,
CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[AspNetUserClaims] WITH CHECK ADD CONSTRAINT [FK_dbo.AspNetUserClaims_dbo.AspNetUsers_UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[AspNetUsers] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[AspNetUserClaims] CHECK CONSTRAINT [FK_dbo.AspNetUserClaims_dbo.AspNetUsers_UserId]
GO
ALTER TABLE [dbo].[AspNetUserLogins] WITH CHECK ADD CONSTRAINT [FK_dbo.AspNetUserLogins_dbo.AspNetUsers_UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[AspNetUsers] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[AspNetUserLogins] CHECK CONSTRAINT [FK_dbo.AspNetUserLogins_dbo.AspNetUsers_UserId]
GO
ALTER TABLE [dbo].[AspNetUserRoles] WITH CHECK ADD CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetRoles_RoleId] FOREIGN KEY([RoleId])
REFERENCES [dbo].[AspNetRoles] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[AspNetUserRoles] CHECK CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetRoles_RoleId]
GO
ALTER TABLE [dbo].[AspNetUserRoles] WITH CHECK ADD CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetUsers_UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[AspNetUsers] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[AspNetUserRoles] CHECK CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetUsers_UserId]
GO
检查并解决任何剩余的错误,您就完成了。身份将处理其余的 :)
【讨论】:
非常感谢您的回复和很好的解释。其实我想用另一种方法,但我也会尝试一下。投票+ 我认为这是一种更清洁的方法 除了 Startup.Auth.cs 类之外,您还需要复制位于示例项目根目录的 Startup.cs。 Shyamal 你能从@Padmika 的评论中添加 Startup.cs 吗?这很重要。【参考方案3】:我推荐IdentityServer。这是一个.NET Foundation 项目,涵盖了有关身份验证和授权的许多问题。
概述
IdentityServer 是一个基于 .NET/Katana 的框架和可托管组件,允许使用 OpenID Connect 和 OAuth2 等协议为现代 Web 应用程序和 API 实施单点登录和访问控制。它支持各种客户端,例如移动、Web、SPA 和桌面应用程序,并且可以扩展以允许集成到新的和现有的架构中。
如需了解更多信息,例如
支持 MembershipReboot 和基于 ASP.NET 身份的用户存储 支持额外的 Katana 身份验证中间件(例如 Google、 推特、脸书等) 支持基于 EntityFramework 的配置持久性 支持 WS-Federation 可扩展性查看documentation 和demo。
【讨论】:
在盲目跳入 IdentityServer 实现之前,应考虑 IdentityServer 的实际用途。【参考方案4】:好吧,我知道我可能为时已晚。 这适用于那些已经进行过一次或多次迁移的人。那些项目运行良好,那些在数据库中有 AspNet 表,但没有与这些相关的控制器、模型和视图。 我也遇到了同样的问题。我在开始时没有激活身份验证就开始了我的项目。然后我意识到我没有用于身份验证的所有元素(Views 文件夹中的 Account 和 Manage,控制器中的 accountController 和 ManageControler,以及模型中的 AccountViewModel 和 ManageViewModel)。 我刚刚创建了具有类似设置、名称的其他项目,并在创建该项目时激活了身份验证。 然后我设法将丢失的文件复制到我的初始项目中。 在那之后,我经历了每一个改变命名空间和导入到我项目的命名空间
【讨论】:
以上是关于将 ASP.NET MVC5 身份验证添加到现有项目的主要内容,如果未能解决你的问题,请参考以下文章
ASP.Net MVC 5 身份验证与另一个 MVC 5 身份网站
如何使用 ASP.NET Core Identity 将登录/注册系统添加到现有数据库?
ASP.NET MVC5 OWIN Facebook 身份验证突然不起作用
我们可以在不使用 ASP.Net Identity 的情况下使用 MVC 5 提供的 cookie 身份验证吗?