я реализовал пользовательский профиль объекта в коде, как описано Joel здесь:Использование членства ASP.NET и профиля с MVC, как я могу создать пользователя и установить его в HttpContext.Current.User?
Я не могу заставить его работать, когда я создаю новый пользователь, однако. Когда я делаю это:
Membership.CreateUser(userName, password);
Roles.AddUserToRole(userName, "MyRole");
пользователь создается и добавляется к роли в базе данных, но HttpContext.Current.User
по-прежнему пуст, и Membership.GetUser()
возвращает нуль, так что это (из кода Джоэла) не работает:
static public AccountProfile CurrentUser
{
get { return (AccountProfile)
(ProfileBase.Create(Membership.GetUser().UserName)); }
}
AccountProfile.CurrentUser.FullName = "Snoopy";
Я пытался дозвониться Membership.GetUser(userName)
и настройка профиля свойств, что путь, но заданные свойства остаются пустыми, и называя AccountProfile.CurrentUser(userName).Save()
ничего не положить в базе данных. Я также попытался указать, что пользователь действителен & вошел в систему, позвонив по номеру Membership.ValidateUser
, FormsAuthentication.SetAuthCookie
и т. Д., Но текущий пользователь по-прежнему является нулевым или анонимным (в зависимости от состояния файлов cookie моего браузера).
SOLVED (ИЗОБРАЖЕН ДАЛЬШЕ, ВИДЕТЬ НИЖЕ): Основываясь на объяснениях Франци Пенова и некоторых дополнительных экспериментах, я выяснил эту проблему. Код Джоэля и варианты, которые я пробовал, будут работать только с существующим профилем. Если профиль отсутствует, ProfileBase.Create(userName)
будет возвращать новый пустой объект при каждом его вызове; вы можете установить свойства, но они не будут «прилипать», потому что новый экземпляр возвращается каждый раз, когда вы обращаетесь к нему. Установка HttpContext.Current.User
к новому GenericPrincipal
будет дать вам объект пользователя, но не объект Профиль и ProfileBase.Create(userName)
и HttpContext.Current.Profile
будет по-прежнему указывают на новые, пустые объекты.
Если вы хотите создать профиль для вновь созданного Пользователя в том же запросе, вам необходимо позвонить HttpContext.Current.Profile.Initialize(userName, true)
. Затем вы можете заполнить инициализированный профиль и сохранить его, и он будет доступен для будущих запросов по имени, поэтому код Джоэла будет работать. Я только используя HttpContext.Current.Profile
внутренне, когда мне нужно создать/получить доступ к профилю сразу после создания. По любым другим запросам я использую ProfileBase.Create(userName)
, и я раскрыл только эту версию как общедоступную.
Обратите внимание, что Franci прав. Если вы желаете создать пользователя (и роли) и установить его как аутентифицированный в первом раунде, и попросите пользователя войти в систему, вы сможете получить доступ к Профиль намного проще с помощью кода Джоэля при последующем запросе. Что меня бросило, так это то, что роли сразу же доступны при создании пользователя без какой-либо инициализации, но профиль - нет.
Мой новый код АккаунтПрофиль:
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; }
}
Создание нового пользователя:
MembershipUser user = Membership.CreateUser(userName, password);
Roles.AddUserToRole(userName, "MyBasicUserRole");
AccountProfile.NewUser.Initialize(userName, true);
AccountProfile.NewUser.FullName = "Snoopy";
AccountProfile.NewUser.Save();
Последующий доступ:
if (Membership.ValidateUser(userName, password))
{
string name = AccountProfile.CurrentUser.FullName;
}
Далее благодаря Франки для объяснения жизни Authentication цикла - I» m вызывает FormsAuthentication.SetAuthCookie в моей функции проверки, но я возвращаю bo ol, чтобы указать успех, поскольку User.Identity.IsAuthenticated не будет истинным до последующего запроса.
ПЕРЕСМОТРЕННЫЙ: Я идиот. Вышеуказанное объяснение работает в узком случае, но не решает основной проблемы: вызов CurrentUser каждый раз возвращает новый экземпляр объекта, независимо от того, является ли он существующим профилем или нет. Потому что это определяется как свойство, я не думал об этом, и написал:
AccountProfile.CurrentUser.FullName = "Snoopy";
AccountProfile.CurrentUser.OtherProperty = "ABC";
AccountProfile.CurrentUser.Save();
, который (конечно же) не работает. Оно должно быть:
AccountProfile currentProfile = AccountProfile.CurrentUser;
currentProfile.FullName = "Snoopy";
currentProfile.OtherProperty = "ABC";
currentProfile.Save();
Это моя вина для полностью вида этого основного вопроса, но я думаю, что объявляя CurrentUser как свойство означает, что это объект, который можно манипулировать. Вместо этого он должен быть объявлен как GetCurrentUser()
.
Будет ли эта работа выдает себя за другого пользователя, а? –
Олицетворение обычно подразумевает проверку подлинности Windows, для которой требуется WindowsPrincipal. Олицетворение может быть сделано из маркера безопасности для олицетворенного пользователя или из учетных данных. Учитывая, что текущий контекст не аутентифицирован, возможно, нет способа получить токен безопасности для пользователя. Таким образом, единственный выбор олицетворяет учетные данные. Возможно, можно создать WindowsPrincipal с надлежащей идентификацией, вызвав LogonUser (если код знает учетные данные для пользователя Windows). Тем не менее, я не пробовал это, поэтому я не могу ручаться, это обязательно сработает. –
Это невероятно полезное объяснение, спасибо.Создание GenericPrincipal (из моего FormsAuthenticationTicket) позволило мне установить HttpContext.Current.User. Тем не менее, я все еще не могу установить значения профиля. Если я использую ProfileBase.Create (Membership.GetUser(). UserName) .SetPropertyValue, ничего не происходит - он больше не генерирует исключение, но свойство остается пустым. Если я использую HttpContext.Current.Profile.SetPropertyValue, он говорит, что я не могу установить свойства в анонимном профиле, подразумевая, что это разные объекты профиля, которые мне как-то нужно объединить. –