Aggiunta dell'autenticazione dell'identità ASP.NET MVC5 a un progetto esistente


164

Ho visto molte pagine simili sul Web, ma la maggior parte di esse utilizza un nuovo progetto anziché uno esistente o non dispone delle funzionalità necessarie. Quindi, ho un MVC 5progetto esistente e voglio integrare ASP.NET MVC5 Identity con funzionalità di accesso, conferma e-mail e reimpostazione della password .

Oltre a ciò, devo anche creare tutte le tabelle necessarie sul database, ad esempio utente, ruoli, gruppi, ecc. (Uso il codice EF First nel mio progetto). C'è un articolo o un campione che corrisponde a queste esigenze? Qualsiasi suggerimento sarebbe apprezzato. Grazie in anticipo...


Che grande queston e che semplice soluzione data proprio sotto. Mi è piaciuto leggere e non avevo molto bisogno di integrarmi nel mio progetto esistente.
Ishwor Khanal,

Risposte:


282

Configurare Identity per il tuo progetto esistente non è cosa difficile. È necessario installare un pacchetto NuGet ed eseguire alcune piccole configurazioni.

Prima installa questi pacchetti NuGet con la console di Package Manager:

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

Aggiungi una classe utente e con IdentityUsereredità:

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

Fai la stessa cosa per il ruolo:

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

Cambia il tuo DbContextgenitore da DbContextin IdentityDbContext<AppUser>questo modo:

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

Se si utilizza la stessa stringa di connessione e si abilita la migrazione, EF creerà le tabelle necessarie per l'utente.

Facoltativamente, è possibile estendere UserManagerper aggiungere la configurazione e la personalizzazione desiderate:

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

Poiché Identity si basa su OWIN, è necessario configurare anche OWIN:

Aggiungi una classe alla App_Startcartella (o altrove se lo desideri). Questa classe è utilizzata da OWIN. Questa sarà la tua classe di avvio.

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

Quasi fatto basta aggiungere questa riga di codice al tuo web.configfile in modo che OWIN possa trovare la tua classe di avvio.

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

Ora, nell'intero progetto, è possibile utilizzare Identity proprio come qualsiasi nuovo progetto era già stato installato da VS. Prendi in considerazione l'azione di accesso, ad esempio

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

Potresti creare ruoli e aggiungere ai tuoi utenti:

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

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

Puoi anche aggiungere un ruolo a un utente, in questo modo:

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

Usando Authorizepotresti proteggere le tue azioni o controller:

[Authorize]
public ActionResult MySecretAction() {}

o

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

Puoi anche installare pacchetti aggiuntivi e configurarli per soddisfare le tue esigenze come Microsoft.Owin.Security.Facebooko come desideri.

Nota: non dimenticare di aggiungere spazi dei nomi rilevanti ai tuoi file:

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;

Potresti anche vedere altre mie risposte come questa e questa per un uso avanzato di Identity.


2
Entrambe le soluzioni sembrano simili. Ho usato AppRoleil ruolo manager di Identity per classificare l'utente. E dal momento che Roles e RoleManagerhanno già implementato da Identity per sé non è necessario riscrivere il codice già implementato. Aggiornerò il post per mostrarti come utilizzare i ruoli. E come ho detto prima, hai solo bisogno di aggiungere AppUsered AppRoleentità per inizializzare Identità. Ereditando il tuo DbContextda IdentityDbContext<AppUser>tutte le tabelle necessarie aggiungi la tua tabella. Non devi fare altro che abilitare la migrazione.
Sam Farajpour Ghamari,

2
Ho appena aggiunto alcuni esempi di utilizzo. Installa Microsoft.AspNet.Identity.EntityFrameworksul tuo dominio e altro per l'interfaccia utente.
Sam Farajpour Ghamari,

2
1) Non preoccuparti per il tuo web.config. Non sostituire quello vecchio. Leggi questo per maggiori informazioni . Penso che anche il tuo MVC sia stato aggiornato.
Sam Farajpour Ghamari

1
2) Hai fatto bene. 3) nessun problema. Avrai 5 nuovi tavoli AspNetRoles AspNetUserClaims AspNetUserLogins AspNetUserRoleseAspNetUsers
Sam Farajpour Ghamari il

3
Ho appena letto tutti i commenti che hai lasciato aiutando Clint Eastwood, Bel lavoro !! Il mondo ha bisogno di più persone come te plusOne
Chef_Code

24

Questo è quello che ho fatto per integrare Identity con un database esistente.

  1. Creare un progetto MVC di esempio con il modello MVC. Questo ha tutto il codice necessario per l'implementazione di Identity: Startup.Auth.cs, IdentityConfig.cs, codice Controller account, Gestisci controller, Modelli e viste correlate.

  2. Installa i pacchetti nuget necessari per Identity e OWIN. Otterrai un'idea vedendo i riferimenti nel progetto di esempio e la risposta di @Sam

  3. Copia tutto questo codice nel tuo progetto esistente. Nota: non dimenticare di aggiungere la stringa di connessione "DefaultConnection" affinché Identity sia mappata al tuo database. Controlla la classe ApplicationDBContext in IdentityModel.cs dove troverai il riferimento alla stringa di connessione "DefaultConnection".

  4. Questo è lo script SQL che ho eseguito sul mio database esistente per creare le tabelle necessarie:

    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. Controlla e risolvi gli eventuali errori rimanenti e il gioco è fatto. L'identità gestirà il resto :)


1
Mille grazie per la risposta e belle spiegazioni. In realtà penso di usare un altro approccio, ma lo proverò anche. Votato +
Jack il

2
Penso che questo sia un approccio molto più pulito
niico

3
Oltre alla classe Startup.Auth.cs è necessario copiare Startup.cs che si trova nella radice del progetto di esempio.
Padmika,

Shyamal puoi aggiungere Startup.cs dal commento di @ Padmika? Questo è importante.
Mike,

4

Raccomando IdentityServer . Questo è un progetto .NET Foundation e copre molti problemi di autenticazione e autorizzazione.

Panoramica

IdentityServer è un framework basato su .NET / Katana e un componente hostable che consente di implementare il single sign-on e il controllo degli accessi per le moderne applicazioni Web e API utilizzando protocolli come OpenID Connect e OAuth2. Supporta una vasta gamma di client come mobile, web, SPA e applicazioni desktop ed è estensibile per consentire l'integrazione in architetture nuove ed esistenti.

Per ulteriori informazioni, ad es

  • supporto per gli store di utenti basati su MembershipReboot e ASP.NET Identity
  • supporto per middleware di autenticazione Katana aggiuntivo (ad es. Google, Twitter, Facebook ecc.)
  • supporto per la persistenza della configurazione basata su EntityFramework
  • supporto per WS-Federation
  • estensibilità

controlla la documentazione e la demo .


6
Gli usi pratici di IdentityServer devono essere considerati prima di saltare ciecamente in un'implementazione di IdentityServer.
hanzolo,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.