wake-up-neo.com

Benutzerdefinierte Authentifizierung in ASP.Net-Core

Ich arbeite an einer Web-App, die in eine vorhandene Benutzerdatenbank integriert werden muss. Ich würde immer noch gerne das [Authorize]-Attribute, aber ich möchte das Identity-Framework nicht verwenden. Wenn ich das Identity-Framework verwenden möchte, füge ich Folgendes in die Datei startup.cs ein:

services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
    options.Password.RequireNonLetterOrDigit = false;
}).AddEntityFrameworkStores<ApplicationDbContext>()
  .AddDefaultTokenProviders();

Ich gehe davon aus, dass ich dort etwas anderes hinzufügen und dann eine Art Klasse erstellen muss, die eine bestimmte Schnittstelle implementiert. Kann mich jemand in die richtige Richtung weisen? Ich benutze gerade RC1 von asp.net 5.

55
rgvassar

Das Erstellen einer benutzerdefinierten Authentifizierung in ASP.NET Core kann auf verschiedene Arten erfolgen. Wenn Sie vorhandene Komponenten ausbauen möchten (aber keine Identität verwenden möchten), lesen Sie die Dokumentenkategorie "Sicherheit" auf docs.asp.net. https://docs.asp.net/en/latest/security/index.html

Einige Artikel, die für Sie hilfreich sein könnten:

Verwendung von Cookie Middleware ohne ASP.NET-Identität

Benutzerdefinierte richtlinienbasierte Autorisierung

Und falls dies fehlschlägt oder die Dokumentation nicht klar genug ist, finden Sie den Quellcode unter https://github.com/aspnet/Security , der einige Beispiele enthält.

49
natemcmaster

Nach dem, was ich nach einigen Tagen Recherche gelernt habe, ist hier das Handbuch für ASP .Net Core MVC 2.x Benutzerdefinierte Benutzerauthentifizierung

In Startup.cs:

Fügen Sie der ConfigureServices -Methode die folgenden Zeilen hinzu:

public void ConfigureServices(IServiceCollection services)
{

services.AddAuthentication(
    CookieAuthenticationDefaults.AuthenticationScheme
).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,
    options =>
    {
        options.LoginPath = "/Account/Login";
        options.LogoutPath = "/Account/Logout";
    });

    services.AddMvc();

    // authentication 
    services.AddAuthentication(options =>
    {
       options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    });

    services.AddTransient(
        m => new UserManager(
            Configuration
                .GetValue<string>(
                    DEFAULT_CONNECTIONSTRING //this is a string constant
                )
            )
        );
     services.AddDistributedMemoryCache();
}

denken Sie daran, dass wir im obigen Code gesagt haben, wenn ein nicht authentifizierter Benutzer eine Aktion anfordert, die mit [Authorize] kommentiert ist, wird die Weiterleitung zur /Account/Login - URL erzwungen.

Fügen Sie der Configure -Methode die folgenden Zeilen hinzu:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler(ERROR_URL);
    }
     app.UseStaticFiles();
     app.UseAuthentication();
     app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: DEFAULT_ROUTING);
    });
}

Erstellen Sie Ihre Klasse UserManager, die auch die An- und Abmeldung verwaltet. Es sollte wie folgt aussehen:

public class UserManager
{
    string _connectionString;

    public UserManager(string connectionString)
    {
        _connectionString = connectionString;
    }

    public async void SignIn(HttpContext httpContext, UserDbModel user, bool isPersistent = false)
    {
        using (var con = new SqlConnection(_connectionString))
        {
            var queryString = "sp_user_login";
            var dbUserData = con.Query<UserDbModel>(
                queryString,
                new
                {
                    UserEmail = user.UserEmail,
                    UserPassword = user.UserPassword,
                    UserCellphone = user.UserCellphone
                },
                commandType: CommandType.StoredProcedure
            ).FirstOrDefault();

            ClaimsIdentity identity = new ClaimsIdentity(this.GetUserClaims(dbUserData), CookieAuthenticationDefaults.AuthenticationScheme);
            ClaimsPrincipal principal = new ClaimsPrincipal(identity);

            await httpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
        }
    }

    public async void SignOut(HttpContext httpContext)
    {
        await httpContext.SignOutAsync();
    }

    private IEnumerable<Claim> GetUserClaims(UserDbModel user)
    {
        List<Claim> claims = new List<Claim>();

        claims.Add(new Claim(ClaimTypes.NameIdentifier, user.Id().ToString()));
        claims.Add(new Claim(ClaimTypes.Name, user.UserFirstName));
        claims.Add(new Claim(ClaimTypes.Email, user.UserEmail));
        claims.AddRange(this.GetUserRoleClaims(user));
        return claims;
    }

    private IEnumerable<Claim> GetUserRoleClaims(UserDbModel user)
    {
        List<Claim> claims = new List<Claim>();

        claims.Add(new Claim(ClaimTypes.NameIdentifier, user.Id().ToString()));
        claims.Add(new Claim(ClaimTypes.Role, user.UserPermissionType.ToString()));
        return claims;
    }
}

Dann haben Sie vielleicht eine AccountController, die eine Login -Aktion hat, die wie folgt aussehen sollte:

public class AccountController : Controller
{
    UserManager _userManager;

    public AccountController(UserManager userManager)
    {
        _userManager = userManager;
    }

    [HttpPost]
    public IActionResult LogIn(LogInViewModel form)
    {
        if (!ModelState.IsValid)
            return View(form);
         try
        {
            //authenticate
            var user = new UserDbModel()
            {
                UserEmail = form.Email,
                UserCellphone = form.Cellphone,
                UserPassword = form.Password
            };
            _userManager.SignIn(this.HttpContext, user);
             return RedirectToAction("Search", "Home", null);
         }
         catch (Exception ex)
         {
            ModelState.AddModelError("summary", ex.Message);
            return View(form);
         }
    }
}

Jetzt können Sie die Annotation [Authorize] Für jedes Action oder Controller verwenden.

Fühlen Sie sich frei, Fragen oder Fehler zu kommentieren.

57
AmiNadimi