2013-08-24 2 views
0

Что лучший способ для аутентификации пользователей сети и хранения их детали, которые у меня есть класс для:asp.net аутентификации пользователей лучших методов WebForms

Должен ли я использовать сеансы или формы аутентификации печенье?

Как я могу получить к нему доступ в любом случае, например userclass.username?

Я хотел бы хранить довольно много информации о пользователях, чтобы остановить вызовы базы данных для таких вещей, как: тип пользователя, имя пользователя, адреса, почтовый индекс, foo1, foo2, foo3, foo4 и многое другое. Я знаю, что это может быть в пользовательских данных сессии или auth cookie. Этот вопрос относится и относится к https://stackoverflow.com/questions/18393122/whats-the-best-way-to-authenticate-a-user-and-store-user-details-sessions-or-fo, который я не имел никакой помощи по адресу

Действительно, я мог бы с некоторой помощью и советом здесь, поскольку у меня есть несколько систем, для которых мне нужно это сделать. Любые комментарии оценены.

благодаря

************************************ Ссылки **** *************************

Мой код, основанный примерно на:

http://www.shawnmclean.com/blog/2012/01/storing-strongly-typed-object-user-profile-data-in-asp-net-forms-authentication-cookie/

http://www.danharman.net/2011/07/07/storing-custom-data-in-forms-authentication-tickets/

* *********************************** РЕДАКТИРОВАТЬ ************** ***************

пользовательский модуль идентификации

Public Module IdentityExtensions 
Sub New() 
End Sub 

Private _CustomIdentityUser As CustomIdentityUser 

<System.Runtime.CompilerServices.Extension> _ 
Public Function CustomIdentity(identity As System.Security.Principal.IIdentity) As CustomIdentityUser 
    'If _CustomIdentityUser Is Nothing Then 
    '_CustomIdentityUser = DirectCast(identity, CustomIdentityUser) 
    _CustomIdentityUser = Nothing 
    If identity.GetType = GetType(FormsIdentity) Then 
     _CustomIdentityUser = New CustomIdentityUser(DirectCast(identity, FormsIdentity).Ticket) 
    Else 
     If identity.IsAuthenticated Then 
      FormsAuthentication.RedirectToLoginPage() 
     End If 
    End If 

    Return _CustomIdentityUser 
End Function 
End Module 

Мой пользователь Пользовательские идентичность

Public Class CustomIdentityUser 
Implements System.Security.Principal.IIdentity 

Private ticket As System.Web.Security.FormsAuthenticationTicket 
Private _Auth As Auth 

Public Sub New(ticket As System.Web.Security.FormsAuthenticationTicket) 
    Me.ticket = ticket 
    _Auth = New projectabc.Auth(Me.ticket) 
End Sub 

Public ReadOnly Property Auth As Auth 
    Get 
     Return Me._Auth 
    End Get 
End Property 
Public ReadOnly Property Username As String 
    Get 
     Return Auth.Username 
    End Get 
End Property 

Public ReadOnly Property UserType As Enumerations.EnumUserType 
    Get 
     Return Auth.UserType 
    End Get 
End Property 
Public ReadOnly Property OwnerType As Enumerations.EnumOwnerType 
    Get 
     Return Auth.OwnerType 
    End Get 
End Property 


Public ReadOnly Property AuthenticationType As String Implements System.Security.Principal.IIdentity.AuthenticationType 
    Get 
     Return "Custom" 
    End Get 
End Property 

Public ReadOnly Property IsAuthenticated As Boolean Implements System.Security.Principal.IIdentity.IsAuthenticated 
    Get 
     Return ticket IsNot Nothing 
    End Get 
End Property 

Public ReadOnly Property Name As String Implements System.Security.Principal.IIdentity.Name 
    Get 
     Return Username 
    End Get 
End Property 
End Class 

Тогда как вы можете видеть класс пользователей вызывает класс аутентификации, который в основном имеет все свойства пользователя и получает и установить его и т.д.

Public Class Auth 
Inherits BaseUser 

Public Property _ticket As Web.Security.FormsAuthenticationTicket 
Public RememberMe As Boolean 

Private _IssueDate As DateTime? 
Public ReadOnly Property IssueDate As DateTime? 
    Get 
     Return _IssueDate 
    End Get 
End Property 
Private _Expired As Boolean 
Public ReadOnly Property Expired As Boolean 
    Get 
     Return _Expired 
    End Get 
End Property 
Private _Expiration As DateTime? 
Public ReadOnly Property Expiration As DateTime? 
    Get 
     Return _Expiration 
    End Get 
End Property 

Public Sub New(ticket As System.Web.Security.FormsAuthenticationTicket) 
    Me._ticket = ticket 
    Dim SignOutUser As Boolean = False 
    Try 
     If Not GetUserDetails() Then 
      SignOutUser = True 
     End If 
    Catch ex As Exception 
     SignOutUser = True 
    End Try 
    If SignOutUser Then 
     HttpContext.Current.Response.Redirect("~/", True) 
     SignOut() 
    End If 
End Sub 

Public ReadOnly Property IsAuthenticated() As Boolean 
    Get 
     Return HttpContext.Current.User.Identity.IsAuthenticated 
    End Get 
End Property 

Public Function SetAuthCookie() As Int16 
    Dim encTicket As String 
    Dim userData As String = CreateUserDataString() 
    If userData.Length > 0 And userData.Length < 4000 Then 
     Dim cookiex As HttpCookie = FormsAuthentication.GetAuthCookie(MyBase.Username, True) 
     Dim ticketx As FormsAuthenticationTicket = FormsAuthentication.Decrypt(cookiex.Value) 

     'Dim newTicket = New FormsAuthenticationTicket(ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration, ticket.IsPersistent, userData, ticket.CookiePath) 
     'encTicket = FormsAuthentication.Encrypt(newTicket) 

     'Use existing cookie. Could create new one but would have to copy settings over... 
     'cookie.Value = encTicket 
     'cookie.Expires = newTicket.Expiration.AddHours(24) 

     'HttpContext.Current.Response.Cookies.Add(cookie) 
     Dim ticket As New FormsAuthenticationTicket(1, ticketx.Name, DateTime.Now, ticketx.Expiration, False, userData, ticketx.CookiePath) 
     encTicket = FormsAuthentication.Encrypt(ticket) 
     cookiex.Value = encTicket 
     'Dim cookie As New HttpCookie(FormsAuthentication.FormsCookieName, encTicket) 

     HttpContext.Current.Response.Cookies.Add(cookiex) 
    Else 
     Throw New ArgumentOutOfRangeException("User data length exceeds maximum", New ArgumentOutOfRangeException) 
    End If 

    Return encTicket.Length 
End Function 

Public Function GetUserDetails() As Boolean 
    Dim valid As Boolean = False  

    If _ticket IsNot Nothing Then 
     With _ticket 
      RememberMe = .IsPersistent 
      Username = .Name 
      _IssueDate = .IssueDate 
      _Expired = .Expired 
      _Expiration = .Expiration 

      Try 
       If .UserData.Length > 0 Then 
        valid = SetUserDataFromString(.UserData) 
       Else 
        'we have a problem 
        Return False 
       End If 
      Catch ex As Exception 
       'sign them out as they may have a cookie but the code may have changed so it errors thus make them login again. 
       'SignOut() 
       Throw ex 

      End Try 
     End With 
    End If 

    Return valid 

End Function 

Private Function CreateUserDataString() As String 
    Dim sData As New System.Text.StringBuilder 

    With sData 
     .Append(MyBase.UserID) 
     .Append("|") 'delimeter we are using 
     .Append(Int16.Parse(MyBase.UserType)) 
     .Append("|") 
     .Append(Int16.Parse(MyBase.Security)) 
     .Append("|") 'delimeter we are using 
     .Append(MyBase.FirstName) 
     .Append("|") 
     .Append(MyBase.LastName) 
    .Append("|") 
     .Append(MyBase.foo1) 
    .Append("|") 
     .Append(MyBase.foo2) 
     .Append("|")    
     .Append(MyBase.foo3) 
    .Append("|") 
     .Append(MyBase.foo4) 
    End With 


    Return sData.ToString 
End Function  

    Public Function SetUserDataFromString(userData As String) As Boolean 
    Dim valid As Boolean = False 
    Dim sData As New System.Text.StringBuilder 
    'check we have a delimeter 
    Dim arUserData As String() = userData.Split("|") 
    Try 


    If arUserData.Count >= 9 Then '9 because that the user only stuff 
     With arUserData 
      MyBase.UserID = arUserData(0) 
      MyBase.UserType = arUserData(1) 
      MyBase.Security = arUserData(2) 
      MyBase.FirstName = arUserData(3) 
      MyBase.LastName = arUserData(4) 
      MyBase.foo1 = arUserData(5) 
    MyBase.foo2 = arUserData(6) 
    MyBase.foo3 = arUserData(7) 
    MyBase.foo4 = arUserData(8) 
     End With 
     valid = True 
    Else 
     valid = False 
     End If 

    Catch ex As Exception 
     Throw New ArgumentOutOfRangeException("User data length to short", New ArgumentOutOfRangeException) 
    End Try 
    Return valid 
End Function 

Public Sub SignOut() 
    FormsAuthentication.SignOut() 
End Sub 
+0

Я осуществил аналогичный аутентификация в двух проектах с использованием пользовательского удостоверения (используя бланки auth ticket), и это доказало быть лучшим вариантом для хранения пользовательских данных, которые вы собираетесь использовать снова и снова для каждого запроса. В другом сообщении я не понял, почему вам не нравится создавать экземпляр индивидуального идентификатора для каждого запроса! Вы можете объяснить? Насколько тяжело вы думаете, что это могло бы создать экземпляр индивидуальности? – Nilesh

+0

Спасибо за ответ. Мне кажется, что я должен делать это неправильно для каждого запроса для любого пользовательского свойства пользовательских данных, которые создаются классом. Так, например, userdata.firstname call и userdata.lastname создают класс дважды. Творит ли ты это. – Jonnymaboy

+0

Нет. Вам нужно расшифровать данные пользователя, а затем установить все свойства в одной инициализации объекта. Можете ли вы отредактировать сообщение и добавить код, как вы создаете экземпляр пользовательского принципала? – Nilesh

ответ

1

Как вы уже разместили код, возможно, вы получите хороший ответ. Я постараюсь ответить в соответствии с моим пониманием, надеюсь, что это поможет. Я долгое время находился вне пределов досягаемости VB, так что голый со мной, если это не имеет смысла.

  1. Откуда вы ссылаетесь на CustomIdentity? В первом методе в Else part я думаю, вы можете использовать Not IsAuthenticated, если вы хотите, чтобы пользователь перенаправлялся на страницу входа. В большинстве случаев, если билет недействителен, вам даже не нужно делать это, он делает это для вас.
  2. В CustomIdentityUser у вас есть частный член _Auth, который вы никогда не используете, возвращая некоторые значения через свойства. Вы используете Auth.UserName вместо _Auth.UserName, я не уверен, как это работает, если UserName не является статическим членом.
  3. Почему вы являетесь пользователем Идентичность в зависимости от Auth? Вы можете передать требуемые данные пользовательскому удостоверению через конструктор или подвергнуть общественность setters. Зачем вам нужен билет авторизации внутри удостоверения?
  4. Auth Класс имеет срок годности и прочее, что не требуется. У вас может быть простой класс User, чтобы хранить основные сведения о пользователе.Почему вы перенаправляете пользователя из конструктора Auth?
  5. GetUserDetails и SetUserDataFromString Я не знаю, зачем вам все эти методы. Его справедливый вопрос: Serializing и Deserializing Пользовательский класс.

Я понимаю, что вы, должно быть, упомянули какой-то блог, чтобы реализовать эту аутентификацию, но у вас есть много возможностей для упрощения этого.

Прочитано this сообщение. В частности, как реализуется пользовательский принцип, и как задана функция authticket, и метод PostAuthenticateRequest.

Вот некоторые примеры кода, которые могут помочь

interface ICustomPrincipal : IPrincipal 
{ 
    int UserId { get; set; } 
    string FirstName { get; set; } 
    string LastName { get; set; } 
} 

public class CustomPrincipal : ICustomPrincipal 
{ 
    public CustomPrincipal() 
    { 

    } 

    public CustomPrincipal(string userName) 
    { 
     Identity = new GenericIdentity(userName); 
    } 

    public int UserId 
    { 
     get; 
     set; 
    } 

    public string FirstName 
    { 
     get; 
     set; 
    } 

    public string LastName 
    { 
     get; 
     set; 
    } 

    public IIdentity Identity 
    { 
     get; 
     private set; 
    } 

    public bool IsInRole(string role) 
    { 
     return false; 
    } 

} 

public class User 
{ 
    public string UserName { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string Email { get; set; } 
} 

public static class FormsAuthHelper 
{ 
    public static void SetAuthTicket(User user, HttpContextBase context) 
    { 
     var serializer = new JavaScriptSerializer(); 
     var userData = serializer.Serialize(user); 
     var authTicket = new FormsAuthenticationTicket(
      1, user.UserName, 
      DateTime.Now, DateTime.Now.AddMinutes(30), 
      false, userData); 
     var ticket = FormsAuthentication.Encrypt(authTicket); 
     var faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, ticket); 
     context.Response.Cookies.Add(faCookie); 
    } 

    public static void Logout() 
    { 
     FormsAuthentication.SignOut(); 
     FormsAuthentication.RedirectToLoginPage(); 
    } 

    public static CustomPrincipal GetPrincipal(User user) 
    { 
     return new CustomPrincipal(user.UserName) { FirstName = user.FirstName, LastName = user.LastName, UserId = user.EntityId }; 
    } 
} 

Сообщение Аутентифицировать событие запроса выглядит следующим образом

protected void Application_PostAuthenticateRequest(object sender, EventArgs e) 
{ 
    var authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName]; 
    if (authCookie == null || authCookie.Value == string.Empty) 
     return; 

    try 
    { 
     var ticket = FormsAuthentication.Decrypt(authCookie.Value); 
     var serializer = new JavaScriptSerializer(); 
     var user = serializer.Deserialize<User>(ticket.UserData); 
     var newUser = FormsAuthHelper.GetPrincipal(user); 

     HttpContext.Current.User = newUser; 
    } 
    catch 
    { 
      //do nothing 
    } 
} 

И, наконец, когда пользователь входит в систему

public ActionResult Login(LoginModel loginModel) 
{ 
    if (ModelState.IsValid) 
    { 
     var user = _userRepository.Get(x => x.UserName == loginModel.UserName).SingleOrDefault(); 
     if (user != null && PasswordHash.ValidatePassword(loginModel.Password, user.Password)) 
     { 
     FormsAuthHelper.SetAuthTicket(user, HttpContext); 
     return RedirectToAction("Index", "Home"); 
     } 
     ModelState.AddModelError("NotFound", "User not found"); 
    } 
    return View(loginModel); 
} 
+0

wow большое спасибо за этот отличный ответ. Чтобы ответить на некоторые ваши вопросы: – Jonnymaboy

+0

1. Я действительно не вызываю вызов, это расширение, называемое так называемым доступом к свойствам индивидуальности. 2, частный член _auth устанавливается в sub new, тогда у меня есть публичное свойство auth. поэтому auth просто возвращает _auth. 3: ваше право вообще не нужно. 4: в основном я перенаправляю здесь, если есть какие-либо проблемы с получением сведений о пользователе и назначением свойств, т. Е. Если cookie не истек, и я изменяю порядок свойств, мне нужен пользователь для повторного входа в систему. 5: у меня были дополнительные свойства, зависящие от типа пользователя. Я сделаю тестовое приложение на основе вашего кода. ссылки на блог добавлены в вопрос. Спасибо. – Jonnymaboy

+0

Сообщение имеет много кода, я, возможно, упустил некоторые свойства. :). Надеюсь, что код, который я разместил, помогает вам или, по крайней мере, дает вам возможность узнать больше. – Nilesh

Смежные вопросы