เพิ่ม ASP.NET MVC5 Identity Authentication ให้กับโครงการที่มีอยู่


164

ฉันได้เห็นหน้าเว็บที่คล้ายกันมากมายบนเว็บ แต่ส่วนใหญ่ใช้โครงการใหม่แทนที่จะเป็นเพจที่มีอยู่หรือไม่มีคุณสมบัติที่จำเป็น ดังนั้นฉันมีMVC 5โครงการที่มีอยู่และต้องการรวมASP.NET MVC5 Identity เข้าสู่ระบบยืนยันอีเมลและคุณสมบัติรีเซ็ตรหัสผ่าน

นอกจากนี้ฉันยังต้องสร้างตารางที่จำเป็นทั้งหมดในฐานข้อมูลเช่นผู้ใช้บทบาทกลุ่ม ฯลฯ (ฉันใช้ EF Code First ในโครงการของฉัน) มีบทความหรือตัวอย่างที่สอดคล้องกับความต้องการเหล่านี้หรือไม่? ข้อเสนอแนะใด ๆ ที่จะได้รับการชื่นชม ขอบคุณล่วงหน้า...


ช่างเป็นภารกิจที่ยอดเยี่ยมอะไรและโซลูตินที่เรียบง่ายให้ไว้ด้านล่าง ฉันชอบที่จะอ่านผ่านและจำเป็นอย่างยิ่งที่จะรวมในโครงการที่มีอยู่ของฉันด้วย
Ishwor Khanal

คำตอบ:


282

การกำหนดค่า Identity ให้กับโครงการที่มีอยู่ไม่ใช่เรื่องยาก คุณต้องติดตั้งแพคเกจ NuGet และทำการกำหนดค่าเล็กน้อย

ก่อนติดตั้งแพ็คเกจ NuGet เหล่านี้ด้วย Package Manager Console:

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>

ตอนนี้ในโครงการทั้งหมดคุณสามารถใช้ Identity เช่นเดียวกับโครงการใหม่ใด ๆ ที่ติดตั้งแล้วโดย VS พิจารณาการดำเนินการเข้าสู่ระบบเช่น

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

คุณสามารถเห็นคำตอบอื่น ๆ ของฉันเช่นนี้และสิ่งนี้สำหรับการใช้ Identity ขั้นสูง


2
โซลูชันทั้งสองมีลักษณะคล้ายคลึงกัน ฉันได้ใช้AppRoleและผู้จัดการบทบาทของ Identity เพื่อจำแนกผู้ใช้ และเนื่องจากRoles และRoleManagerมีการใช้งานโดย Identity แล้วคุณไม่จำเป็นต้องเขียนโค้ดใหม่อีกครั้ง ฉันจะอัปเดตโพสต์เพื่อแสดงให้คุณเห็นว่าคุณสามารถใช้บทบาทได้อย่างไร และอย่างที่ฉันพูดก่อนที่คุณจะต้องเพิ่มAppUserและAppRoleเอนทิตีเพื่อเริ่มต้น Identity โดยการสืบทอดของคุณDbContextจากIdentityDbContext<AppUser>ตารางที่จำเป็นทั้งหมดเพิ่มตารางของคุณ คุณไม่จำเป็นต้องทำอะไรเลยเพียงแค่เปิดใช้งานการโยกย้าย
Sam Farajpour Ghamari

2
ฉันเพิ่งเพิ่มตัวอย่างการใช้งาน ติดตั้งMicrosoft.AspNet.Identity.EntityFrameworkไปยังโดเมนของคุณและอื่น ๆ สำหรับ UI
Sam Farajpour Ghamari

2
1) web.configไม่ต้องกังวลเกี่ยวกับคุณ อย่าแทนที่อันเก่า อ่านนี้สำหรับข้อมูลเพิ่มเติม ฉันคิดว่า MVC ของคุณอัพเกรดแล้ว
Sam Farajpour Ghamari

1
2) คุณทำถูกต้อง 3) ไม่มีปัญหา คุณจะได้ 5 โต๊ะใหม่AspNetRoles AspNetUserClaims AspNetUserLogins AspNetUserRolesและAspNetUsers
Sam Farajpour Ghamari

3
ฉันอ่านความคิดเห็นทั้งหมดที่คุณทิ้งไว้เพื่อช่วย Clint Eastwood, Nice Job !! โลกต้องการคนมากกว่าคุณเช่นคุณบวกหนึ่ง
Chef_Code

24

นี่คือสิ่งที่ฉันทำเพื่อรวมข้อมูลประจำตัวกับฐานข้อมูลที่มีอยู่

  1. สร้างโครงการ MVC ตัวอย่างด้วยเทมเพลต MVC นี่คือรหัสทั้งหมดที่จำเป็นสำหรับการติดตั้ง Identity - Startup.Auth.cs, IdentityConfig.cs, รหัสบัญชีผู้ควบคุม, จัดการคอนโทรลเลอร์, รุ่นและมุมมองที่เกี่ยวข้อง

  2. ติดตั้งแพ็กเกจ nuget ที่จำเป็นสำหรับ Identity และ OWIN คุณจะได้รับแนวคิดโดยดูการอ้างอิงในตัวอย่างโครงการและคำตอบโดย @Sam

  3. คัดลอกรหัสเหล่านี้ไปยังโครงการที่มีอยู่ของคุณ โปรดทราบว่าอย่าลืมเพิ่มสตริงการเชื่อมต่อ "DefaultConnection" สำหรับ Identity เพื่อแมปไปยังฐานข้อมูลของคุณ โปรดตรวจสอบคลาส ApplicationDBContext ใน IdentityModel.cs ซึ่งคุณจะพบการอ้างอิงถึงสตริงการเชื่อมต่อ "DefaultConnection"

  4. นี่เป็นสคริปต์ 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
  5. ตรวจสอบและแก้ไขข้อผิดพลาดที่เหลือและคุณทำเสร็จแล้ว ตัวตนจะจัดการกับส่วนที่เหลือ :)


1
ขอบคุณมากสำหรับคำตอบของคุณและคำอธิบายที่ดี ที่จริงฉันคิดว่าจะใช้วิธีอื่น แต่ฉันจะลองด้วย โหวต +
แจ็ค

2
ฉันคิดว่านี่เป็นวิธีที่สะอาดกว่ามาก
niico

3
นอกจากคลาส Startup.Auth.cs คุณต้องคัดลอก Startup.cs ที่อยู่ที่รูทของโปรเจ็กต์ตัวอย่าง
Padmika

Shyamal คุณสามารถเพิ่ม Startup.cs จากความคิดเห็นของ @ Padmika ได้หรือไม่? นี้เป็นสิ่งสำคัญ.
Mike

4

ฉันแนะนำIdentityServerนี่คือ. NET Foundationโครงการและครอบคลุมปัญหามากมายเกี่ยวกับการรับรองความถูกต้องและการอนุญาต

ภาพรวม

IdentityServer เป็นเฟรมเวิร์กที่ใช้. NET / Katana และคอมโพเนนต์ที่โฮสต์ได้ซึ่งอนุญาตให้ใช้การลงชื่อเข้าใช้ครั้งเดียวและการควบคุมการเข้าถึงสำหรับเว็บแอปพลิเคชันและ API ที่ทันสมัยโดยใช้โปรโตคอลเช่น OpenID Connect และ OAuth2 รองรับไคลเอนต์ที่หลากหลายเช่นมือถือเว็บสปาและแอพพลิเคชั่นเดสก์ท็อป

สำหรับข้อมูลเพิ่มเติมเช่น

  • การสนับสนุนสำหรับ MembershipReboot และ ASP.NET Identity ตามร้านค้าผู้ใช้
  • รองรับมิดเดิ้ลการพิสูจน์ตัวตน Katana เพิ่มเติม (เช่น Google, Twitter, Facebook และอื่น ๆ )
  • สนับสนุนการคงอยู่ของการกำหนดค่าตาม EntityFramework
  • การสนับสนุนสำหรับ WS-Federation
  • ขยาย

ตรวจสอบเอกสารและการสาธิต


6
ควรพิจารณาถึงวิธีการใช้งานจริงของ IdentityServer ก่อนที่จะข้ามไปสู่การใช้งาน IdentityServer แบบสุ่ม
hanzolo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.