при использовании стандартной системы аутентификации в asp.net mvc3 в контексте конроллера доступно стовойства User, которое реализует интерфейс System.Security.Principal.IPrincipal.
Все бы хорошо, но в этом контексте доступно только имя пользователя через User.Identity.Name, а вот, например, UserId или чего то подобного увы — нет.
Можно переопределить MembershipProvider, перегрузить метод GetUser(), который вернет объект типа MembershipUser, который, в свою очередь, будет содержать стандартное свойство ProviderUserKey — именно тот идентификатор, который мне и нужен.
Таким образом, для получения userid нужно будет вызвать
1. Каков жизненный цикл объекта, возвращаемого свойством User (тот, который доступен в классе контроллера)?
2. можно ли как то этот жизненный цикл переделать, чтобы после аутентификации контроллеровское свойство User возвращало что-то, что содержало бы UserId, а возможно, что-то еще? (в методе описанном в предыдущих двух абзацах меня смущает то, что метод GetUser() выполняет «большую» работу по извлечению UserId по его имени, причем каждый раз, когда его нужно получить, хочеться получить userid один раз при аутентификации и использовать везде без лишних затрат.)
public IPrincipal User
{
get
{
if (this.HttpContext != null)
return this.HttpContext.User;
else
return (IPrincipal) null;
}
}
Здесь, в общем-то ответ сразу на оба вопроса. Вот типичный пример того, что с этим делают.
Другое дело, что я вам искренне не советую так делать, а советую пользоваться сразу Windows Identity Foundation, в которой любая необходимая вам вещь хранится в так называемых claim, привязанных к текущему принципалу.
Легко. Человек открыл сессию и не закрывает ее. Причем поскольку он умный, у него в браузере стоит авторефреш, и сессия не тухнет. В результате, пока вы не перегрузите приложение, сессия так и останется висеть.
А это, в свою очередь означает, что если вы, допустим, заблокировали пользователя, то он так об этом никогда не узнает.
Понятно. но тогда единственным выходом из этой ситуации является проверка подлинности при каждом реквесте или, скажем, с очень коротким интервалом времени. А WIF как в этом случае поможет?
Спасибо.
С использованием WIF я пока решил повременить.
Если смотреть в сторону использования IPrincipal, то в нем нет места для UserID, но можно сделать собственный класс, реализующий IPrincipal, который будет содержать необходимые свойства, или можно хранить в сессии пользователя дополнительный объект для хранения этих сведений.
Вот тут возникает интересный (для меня) момент: в какой момент эту информацию сохранть в сессии или в HttpContext. Если аутентификация выполняется методом Form, то на странице ввода логина и пароля, но есть еще один интересный момент: пользователь может попросить «запомнить» его, чтобы не вводить в следующий раз логин и пароль, при этом пользователь в следующей сессии будет залогиненым, хотя никакой проверки подлинности произведено не будет и даже пользователя может уже не быть такого на сайте.
В каком месте в этом случае лучше всего формировать контекстную информацию пользователя?
Ну и зря, потому что он бы ответил на ваши вопросы.
в какой момент эту информацию сохранть в сессии или в HttpContext.
Я же вам дал ссылку на событие authenticate. Там можно подставить своего принципала, и дальше уже не думать о том, как и когда asp.net решит его закэшировать.
пользователь может попросить «запомнить» его, чтобы не вводить в следующий раз логин и пароль, при этом пользователь в следующей сессии будет залогиненым, хотя никакой проверки подлинности произведено не будет и даже пользователя может уже не быть такого на сайте.
Во-первых, это можно отключить. А во-вторых, проверка подлинности будет, просто по куке.
authenticate меня смущает тем, что он выполняется при каждом http запросе. Формировать контекст безопасности при каждом http запросе мне кажется неразумным с точки зрения производительности.
Альтернативный вариант — использовать Session_Start в Global.asax. Если ли в этом случае противопоказания?