对于验证网络用户和存储他们的详细信息的最佳方式是什么:
我应该使用会话还是表格auth cookie?
我如何从任何一种方式访问它,比如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.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
然后你可以看到用户类调用一个auth类,它基本上具有用户的所有属性,并获取和设置它等。
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 :(得分:1)
正如您发布的代码可能会得到一些好的答案。我会按照我的理解尝试回答,希望有所帮助。 如果没有意义的话,我已经很久没有接触过VB了。
Not IsAuthenticated
。大多数情况下,如果票证无效,你甚至不必为此做框架。CustomIdentityUser
中,您有一个私有成员_Auth,您在通过属性返回某些值时从未使用过。您使用的是Auth.UserName
而不是_Auth.UserName
,除非UserName是静态成员,否则我不确定它是如何工作的。Auth
?您可以通过构造函数或公开公共setters
将所需数据传递给自定义标识。为什么你需要身份证内的身份证明票? Auth
类具有到期日期和其他不需要的内容。您可以使用简单的User
类来存储用户的基本详细信息。为什么要从Auth
的构造函数重定向用户?GetUserDetails
和SetUserDataFromString
我不知道为什么你需要所有这些方法。它只是Serializing
和Deserializing
User类的问题。 我知道您必须在那里引用一些博客来实现此身份验证,但您有很多范围来简化此操作。
阅读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);
}