Thêm xác thực danh tính ASP.NET MVC5 vào một dự án hiện có


164

Tôi đã thấy rất nhiều trang tương tự trên web, nhưng hầu hết trong số họ sử dụng một dự án mới thay vì một trang hiện có hoặc không có các tính năng cần thiết. Vì vậy, tôi có một MVC 5dự án hiện có và muốn tích hợp ASP.NET MVC5 Nhận dạng với đăng nhập, xác nhận email và các tính năng đặt lại mật khẩu .

Ngoài ra, tôi cũng cần tạo tất cả các bảng cần thiết trên cơ sở dữ liệu, ví dụ như Người dùng, Vai trò, nhóm, v.v. (Tôi sử dụng Mã EF đầu tiên trong dự án của mình). Có một bài viết hoặc mẫu tương ứng với những nhu cầu này? Bất kỳ đề nghị sẽ được đánh giá cao. Cảm ơn trước...


Thật là một nhiệm vụ tuyệt vời và những gì một solutin đơn giản được đưa ra ngay bên dưới. Tôi thích đọc nó và rất cần được tích hợp vào dự án hiện tại của tôi.
Ishwor Khanal

Câu trả lời:


282

Cấu hình danh tính cho dự án hiện tại của bạn không phải là điều khó. Bạn phải cài đặt một số gói NuGet và thực hiện một số cấu hình nhỏ.

Trước tiên hãy cài đặt các gói NuGet này với Gói quản lý gói:

PM> Install-Package Microsoft.AspNet.Identity.Owin 
PM> Install-Package Microsoft.AspNet.Identity.EntityFramework
PM> Install-Package Microsoft.Owin.Host.SystemWeb 

Thêm một lớp người dùng và với IdentityUsersự kế thừa:

public class AppUser : IdentityUser
{
    //add your custom properties which have not included in IdentityUser before
    public string MyExtraProperty { get; set; }  
}

Làm điều tương tự cho vai trò:

public class AppRole : IdentityRole
{
    public AppRole() : base() { }
    public AppRole(string name) : base(name) { }
    // extra properties here 
}

Thay đổi của bạn DbContextmẹ từ DbContextđể IdentityDbContext<AppUser>như thế này:

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>
}

Nếu bạn sử dụng cùng một chuỗi kết nối và cho phép di chuyển, EF sẽ tạo các bảng cần thiết cho bạn.

Tùy chọn, bạn có thể mở rộng UserManagerđể thêm cấu hình và tùy chỉnh mong muốn của mình:

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;
    }
}

Vì Danh tính dựa trên OWIN, bạn cũng cần định cấu hình OWIN:

Thêm một lớp vào App_Startthư mục (hoặc bất cứ nơi nào khác nếu bạn muốn). Lớp này được sử dụng bởi OWIN. Đây sẽ là lớp khởi nghiệp của bạn.

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"),
            });
        }
    }
}

Hầu như hoàn thành chỉ cần thêm dòng mã này vào web.configtệp của bạn để OWIN có thể tìm thấy lớp khởi động của bạn.

<appSettings>
    <!-- other setting here -->
    <add key="owin:AppStartup" value="MyAppNamespace.IdentityConfig" />
</appSettings>

Bây giờ trong toàn bộ dự án, bạn có thể sử dụng Danh tính giống như bất kỳ dự án mới nào đã được cài đặt bởi VS. Xem xét hành động đăng nhập chẳng hạn

[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);
}

Bạn có thể tạo vai trò và thêm vào người dùng của mình:

public ActionResult CreateRole(string roleName)
{
    var roleManager=HttpContext.GetOwinContext().GetUserManager<RoleManager<AppRole>>();

    if (!roleManager.RoleExists(roleName))
        roleManager.Create(new AppRole(roleName));
    // rest of code
} 

Bạn cũng có thể thêm vai trò cho người dùng, như thế này:

UserManager.AddToRole(UserManager.FindByName("username").Id, "roleName");

Bằng cách sử dụng, Authorizebạn có thể bảo vệ hành động hoặc bộ điều khiển của mình:

[Authorize]
public ActionResult MySecretAction() {}

hoặc là

[Authorize(Roles = "Admin")]]
public ActionResult MySecretAction() {}

Bạn cũng có thể cài đặt các gói bổ sung và định cấu hình chúng để đáp ứng yêu cầu của bạn như thế Microsoft.Owin.Security.Facebooknào hoặc bất cứ điều gì bạn muốn.

Lưu ý: Đừng quên thêm các không gian tên có liên quan vào tệp của bạn:

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;

Bạn cũng có thể thấy các câu trả lời khác của tôi như thế này và câu trả lời này để sử dụng Nhận dạng nâng cao.


2
Cả hai giải pháp trông giống nhau. Tôi đã sử dụng AppRolevà quản lý vai trò của Identity để phân loại người dùng. Và kể từ khi Roles và RoleManagerđã thực hiện bằng cách nhận dạng bản thân bạn không cần phải viết lại mã đã được thực hiện. Tôi sẽ cập nhật bài viết để cho bạn thấy làm thế nào bạn có thể sử dụng vai trò. Và như tôi đã nói trước khi bạn chỉ cần thêm AppUserAppRolecác thực thể để khởi tạo Danh tính. Bằng cách kế thừa của bạn DbContexttừ IdentityDbContext<AppUser>tất cả các bảng cần thiết thêm bảng của bạn. Bạn không cần làm bất cứ điều gì chỉ cần kích hoạt di chuyển.
Sam Farajpour Ghamari

2
Tôi chỉ cần thêm một số mẫu sử dụng. Cài đặt Microsoft.AspNet.Identity.EntityFrameworkvào Miền của bạn và khác cho UI.
Sam Farajpour Ghamari

2
1) Đừng lo lắng về bạn web.config. Đừng thay thế cái cũ. Đọc này để biết thêm . Tôi nghĩ rằng MVC của bạn cũng được nâng cấp.
Sam Farajpour Ghamari

1
2) Bạn đã làm đúng. 3) không có vấn đề. Bạn sẽ có 5 bàn mới AspNetRoles AspNetUserClaims AspNetUserLogins AspNetUserRolesAspNetUsers
Sam Farajpour Ghamari

3
Tôi chỉ đọc qua tất cả các ý kiến ​​bạn để lại giúp Clint Eastwood, Nice Job !! Thế giới cần nhiều người hơn như bạn plusOne
Chef_Code

24

Đây là những gì tôi đã làm để tích hợp Danh tính với cơ sở dữ liệu hiện có.

  1. Tạo một dự án MVC mẫu với mẫu MVC. Điều này có tất cả các mã cần thiết để triển khai Danh tính - Startup.Auth.cs, IdentityConfig.cs, Mã điều khiển tài khoản, Quản lý điều khiển, Mô hình và các chế độ xem liên quan.

  2. Cài đặt các gói nuget cần thiết cho Danh tính và OWIN. Bạn sẽ có một ý tưởng bằng cách xem các tài liệu tham khảo trong Dự án mẫu và câu trả lời của @Sam

  3. Sao chép tất cả các mã này vào dự án hiện tại của bạn. Xin lưu ý đừng quên thêm chuỗi kết nối "DefaultConnection" cho Danh tính để ánh xạ vào cơ sở dữ liệu của bạn. Vui lòng kiểm tra lớp ApplicationDBContext trong IdentityModel.cs nơi bạn sẽ tìm thấy tham chiếu đến chuỗi kết nối "DefaultConnection".

  4. Đây là tập lệnh SQL tôi đã chạy trên cơ sở dữ liệu hiện có của mình để tạo các bảng cần thiết:

    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
  5. Kiểm tra và giải quyết bất kỳ lỗi nào còn lại và bạn đã hoàn thành. Danh tính sẽ xử lý phần còn lại :)


1
Rất cám ơn bạn đã trả lời và giải thích tốt đẹp. Thật ra tôi nghĩ đến việc sử dụng một cách tiếp cận khác, nhưng tôi cũng sẽ thử nó. Bình chọn +
Jack

2
Tôi nghĩ rằng đây là một cách tiếp cận sạch sẽ hơn nhiều
niico

3
Ngoài lớp Startup.Auth.cs, bạn cần sao chép Startup.cs nằm ở thư mục gốc của dự án mẫu.
Padmika

Shyamal bạn có thể thêm Startup.cs từ nhận xét của @ Padmika không? Điều này quan trọng.
Mike

4

Tôi khuyên dùng IdentityServer . Đây là một dự án .NET Foundation và bao gồm nhiều vấn đề về xác thực và ủy quyền.

Tổng quat

IdentityServer là một khung và thành phần có thể lưu trữ dựa trên .NET / Katana cho phép thực hiện kiểm soát đăng nhập và kiểm soát truy cập cho các ứng dụng web và API hiện đại bằng các giao thức như OpenID Connect và OAuth2. Nó hỗ trợ một loạt các khách hàng như thiết bị di động, web, SPA và máy tính để bàn và có thể mở rộng để cho phép tích hợp trong các kiến ​​trúc mới và hiện có.

Để biết thêm thông tin, ví dụ

  • hỗ trợ cho các cửa hàng người dùng dựa trên MemberhipReboot và ASP.NET Identity
  • hỗ trợ thêm phần mềm trung gian xác thực Katana (ví dụ: Google, Twitter, Facebook, v.v.)
  • hỗ trợ cho cấu hình bền vững của EntityFramework
  • hỗ trợ cho Liên kết WS
  • mở rộng

kiểm tra tài liệu và các bản demo .


6
Các cách sử dụng thực tế của IdentityServer nên được xem xét trước khi mù quáng nhảy vào triển khai IdentityServer.
hanzolo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.