Jer*_*ald 17 membership profile asp.net-mvc createuser
我在代码中实现了一个自定义的Profile对象,如Joel所述:
但是,当我创建一个新用户时,我无法让它工作.当我这样做:
Membership.CreateUser(userName, password);
Roles.AddUserToRole(userName, "MyRole");
Run Code Online (Sandbox Code Playgroud)
用户是创建并添加到数据库中的角色,但HttpContext.Current.User
仍然是空的,并Membership.GetUser()
返回null,所以这(从Joel的代码)不起作用:
static public AccountProfile CurrentUser
{
get { return (AccountProfile)
(ProfileBase.Create(Membership.GetUser().UserName)); }
}
AccountProfile.CurrentUser.FullName = "Snoopy";
Run Code Online (Sandbox Code Playgroud)
我尝试过这样调用Membership.GetUser(userName)
和设置Profile属性,但是set属性保持为空,并且调用AccountProfile.CurrentUser(userName).Save()
不会在数据库中放置任何内容.我也试着指示用户是有效的和登录,通过调用Membership.ValidateUser
,FormsAuthentication.SetAuthCookie
等等,但是当前用户仍然是空的或匿名的(根据我的浏览器的cookie的状态).
解决(进一步编辑,见下文):根据Franci Penov的解释和一些更多实验,我找出了问题.Joel的代码和我尝试的变体只适用于现有的个人资料.如果不存在Profile,ProfileBase.Create(userName)
则每次调用时都会返回一个新的空对象; 您可以设置属性,但它们不会"粘住",因为每次访问时都会返回一个新实例.设置HttpContext.Current.User
一个新的GenericPrincipal
将会给你一个User对象,但没有一个Profile对象,ProfileBase.Create(userName)
并且HttpContext.Current.Profile
仍将指向新的,空的对象.
如果要在同一请求中为新创建的用户创建配置文件,则需要调用HttpContext.Current.Profile.Initialize(userName, true)
.然后,您可以填充初始化的配置文件并保存它,并且可以在将来的请求中按名称访问它,因此Joel的代码将起作用.我只在HttpContext.Current.Profile
内部使用,当我需要在创建时立即创建/访问配置文件.在任何其他请求,我使用ProfileBase.Create(userName)
,并且我只公开该版本.
请注意,Franci是正确的:如果您愿意创建用户(和角色)并在第一次往返时将其设置为Authenticated,并要求用户再登录,您将能够更简单地访问该配置文件通过Joel的代码来处理后续请求.让我感到震惊的是,Roles可以在用户创建时立即访问,无需任何初始化,但Profile不是.
我的新AccountProfile代码:
public static AccountProfile CurrentUser
{
get
{
if (Membership.GetUser() != null)
return ProfileBase.Create(Membership.GetUser().UserName) as AccountProfile;
else
return null;
}
}
internal static AccountProfile NewUser
{
get { return System.Web.HttpContext.Current.Profile as AccountProfile; }
}
Run Code Online (Sandbox Code Playgroud)
新用户创建:
MembershipUser user = Membership.CreateUser(userName, password);
Roles.AddUserToRole(userName, "MyBasicUserRole");
AccountProfile.NewUser.Initialize(userName, true);
AccountProfile.NewUser.FullName = "Snoopy";
AccountProfile.NewUser.Save();
Run Code Online (Sandbox Code Playgroud)
后续访问:
if (Membership.ValidateUser(userName, password))
{
string name = AccountProfile.CurrentUser.FullName;
}
Run Code Online (Sandbox Code Playgroud)
进一步感谢Franci解释身份验证生命周期 - 我在验证函数中调用了FormsAuthentication.SetAuthCookie,但我返回一个bool来表示成功,因为User.Identity.IsAuthenticated在后续请求之前不会成立.
修订:我是个白痴.以上解释适用于狭义的情况,但不能解决核心问题:每次调用CurrentUser都会返回一个新的对象实例,无论它是否是现有的Profile.因为它被定义为属性,我没有考虑这个,并写道:
AccountProfile.CurrentUser.FullName = "Snoopy";
AccountProfile.CurrentUser.OtherProperty = "ABC";
AccountProfile.CurrentUser.Save();
Run Code Online (Sandbox Code Playgroud)
哪(当然)不起作用.它应该是:
AccountProfile currentProfile = AccountProfile.CurrentUser;
currentProfile.FullName = "Snoopy";
currentProfile.OtherProperty = "ABC";
currentProfile.Save();
Run Code Online (Sandbox Code Playgroud)
完全忽略这个基本点是我自己的错,但我确实认为将CurrentUser声明为属性意味着它是一个可以被操纵的对象.相反,它应该声明为GetCurrentUser()
.
创建用户只需将其添加到用户列表中.但是,这不会对当前请求的新用户进行身份验证或授权.您还需要在当前请求上下文或后续请求中对用户进行身份验证.
Membership.ValidateUser
将仅验证凭据,但不会对当前或后续请求的用户进行身份验证.FormsAuthentication.SetAuthCookie
将在响应流中设置身份验证票证,以便对下一个请求进行身份验证,但不会影响当前请求的状态.
验证用户的最简单方法是调用FormsAuthentication.RedirectFromLoginPage
(假设您在应用程序中使用表单身份验证).但是,这个实际上会导致新的HTTP请求,该请求将对用户进行身份验证.
或者,如果您需要继续处理当前请求的逻辑,但希望对用户进行身份验证,则可以创建a GenericPrincipal
,为其分配新用户的标识并将其设置HttpContext.User
为该主体.
归档时间: |
|
查看次数: |
13723 次 |
最近记录: |