Jak zaimplementować uwierzytelnianie niestandardowe w ASP.NET MVC 5

80

Tworzę aplikację ASP.NET MVC 5. Mam istniejącą bazę danych, z której utworzyłem mój Entity Data Model ADO.NET. Mam tabelę w tej bazie danych, która zawiera kolumny „nazwa użytkownika” i „hasło” i chcę ich użyć do zaimplementowania uwierzytelniania i autoryzacji w mojej aplikacji internetowej; Nie mogę utworzyć innej bazy danych, tabeli lub kolumny i nie mogę korzystać ze standardowego uwierzytelniania tożsamości ze względu na wymagania klienta. Nie muszę zarządzać rejestracją, zmianą hasła ani innymi rzeczami: po prostu zaloguj się za pomocą hasła i nazwy użytkownika. Jak mogę to zrobić?

Giacomo Santarnecchi
źródło

Odpowiedzi:

158

Tak, możesz. Części uwierzytelniania i autoryzacji działają niezależnie. Jeśli masz własną usługę uwierzytelniania, możesz po prostu skorzystać z części autoryzacyjnej OWIN. Rozważ, że masz już plik, UserManagerktóry sprawdza poprawność usernamei password. Dlatego możesz wpisać następujący kod w akcji logowania zwrotnego:

[HttpPost]
public ActionResult Login(string username, string password)
{
    if (new UserManager().IsValid(username, password))
    {
        var ident = new ClaimsIdentity(
          new[] { 
              // adding following 2 claim just for supporting default antiforgery provider
              new Claim(ClaimTypes.NameIdentifier, username),
              new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"),

              new Claim(ClaimTypes.Name,username),

              // optionally you could add roles if any
              new Claim(ClaimTypes.Role, "RoleName"),
              new Claim(ClaimTypes.Role, "AnotherRole"),

          },
          DefaultAuthenticationTypes.ApplicationCookie);

        HttpContext.GetOwinContext().Authentication.SignIn(
           new AuthenticationProperties { IsPersistent = false }, ident);
        return RedirectToAction("MyAction"); // auth succeed 
    }
    // invalid username or password
    ModelState.AddModelError("", "invalid username or password");
    return View();
}

Twój menedżer użytkowników może wyglądać mniej więcej tak:

class UserManager
{
    public bool IsValid(string username, string password)
    {
         using(var db=new MyDbContext()) // use your DbConext
         {
             // for the sake of simplicity I use plain text passwords
             // in real world hashing and salting techniques must be implemented   
             return db.Users.Any(u=>u.Username==username 
                 && u.Password==password); 
         }
    }
}

W końcu możesz chronić swoje akcje lub kontrolery, dodając Authorizeatrybut.

[Authorize]
public ActionResult MySecretAction()
{
    // all authorized users can use this method
    // we have accessed current user principal by calling also
    // HttpContext.User
}

[Authorize(Roles="Admin")]
public ActionResult MySecretAction()
{
    // just Admin users have access to this method
} 
Sam FarajpourGhamari
źródło
7
Właśnie zaktualizowałem swój post, aby odpowiedzieć na Twoje pytania.
Sam FarajpourGhamari
5
Hej, chciałem Ci powiedzieć, że Twój przykład z github (dla tokenauth) rozwiązał moje problemy, wielkie dzięki! Głosowałbym za twoim przykładem 1000 razy, gdybym mógł :)
AME
6
Potrzebne pakiety nuget: - Microsoft.AspNet.Identity.Core - Microsoft.AspNet.Identity.Owin - Microsoft.Owin - Microsoft.Owin.Host.SystemWeb - Microsoft.Owin.Security - Microsoft.Owin.Security.Cookies - Microsoft.Owin .Security.OAuth - Owin
Matthieu
5
Żałuję, że nie masz otwartej nagrody za to pytanie, abyśmy mogli dać ci +1000. Opublikuj to gdzieś na blogu, aby wyszukiwarki mogły to osiągnąć. To takie proste i eleganckie rozwiązanie. Spędziłem dwa dni czytając o OWIN i OAuth2 i nie mogłem podłączyć przewodów.
adopilot
2
@SamFarajpourGhamari: Czy możesz wyjaśnić, dlaczego ten długi ciąg znaków const jest wymagany w Loginkodzie? ... new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string")Sprawdziłem, czy kod działa dobrze bez niego!
S.Serpooshan