Как сайт с переполнением стека может передавать информацию о пользователях в ASP.NET MVC? - PullRequest
4 голосов
/ 23 апреля 2009

По сути, я захожу на свой сайт с использованием OpenId, очень похоже на то, что, как я предполагаю, делает SO. Когда я получаю информацию обратно, я выбрасываю ее в базу данных и создаю своего «Зарегистрированного пользователя». Я установил свой AuthCookie:

FormsAuthentication.SetAuthCookie(user.Profile.MyProfile.DisplayName, false);

Тогда я могу использовать это для имени пользователя. Тем не менее, я хотел бы передать весь объект вместо строки для отображаемого имени. Итак, мой вопрос:

Как ТАК это делает?

Они расширяют / переопределяют метод SetAuthCookie(string, bool) для принятия объекта User, т.е. SetAuthCookie(User(object), bool).

Каков наилучший способ сохранить объект User, чтобы он был доступен моему UserControl на каждой странице моего веб-приложения?

Заранее спасибо!

Ответы [ 3 ]

3 голосов
/ 23 апреля 2009

Вы можете добиться этого поведения, внедрив своего пользовательского поставщика членства или расширив существующего. Поставщик хранит информацию о пользователях на основе ключа (или только по имени пользователя) и предоставляет доступ к классу MembershipUser , который вы можете расширять по своему желанию. Поэтому, когда вы звоните FormsAuthentication.SetAuthCookie(...), вы в основном устанавливаете ключ пользователя, к которому может обращаться провайдер.

Когда вы вызываете Membership.GetUser(), инфраструктура членства вызывает базового поставщика и вызывает его метод GetUser(...), предоставляя ему ключ текущего пользователя. Таким образом вы получите текущий объект пользователя.

2 голосов
/ 24 апреля 2009

Джеф,

Как я уже сказал в комментарии к вашему вопросу выше, вы должны использовать ClaimedIdentifier для имени пользователя, то есть первый параметр SetAuthCookie. Для этого есть огромная причина безопасности. Не стесняйтесь начинать обсуждение по адресу dotnetopenid@googlegroups.com, если вы хотите больше узнать о причинах.

Теперь по поводу вашего вопроса обо всем объекте пользователя ... если вы хотите отправить его в виде куки-файла, вам нужно будет сериализовать ваш объект пользователя в виде строки, тогда вы ДОЛЖНЫ ПОДПИСАТЬ его каким-либо образом. для защиты от вмешательства пользователя. Вы также можете зашифровать его. Бла-бла, это большая работа, и вы получите большой файл cookie, который отправляется туда-сюда с каждым веб-запросом, который вам не нужен.

Что я делаю в своих приложениях, чтобы решить проблему, о которой вы говорите, - добавить статическое свойство в мой файл Global.asax.cs с именем CurrentUser. Как это:

public static User CurrentUser {
    get {
        User user = HttpContext.Current.Items["CurrentUser"] as User;
        if (user == null && HttpContext.Current.User.Identity.IsAuthenticated) {
            user = Database.LookupUserByClaimedIdentifier(HttpContext.Current.User.Identity.Name);
            HttpContext.Current.Items["CurrentUser"] = user;
        }
        return user;
    }
}

Обратите внимание, что я кеширую результат в словаре HttpContext.Current.Items, который относится к одному HTTP-запросу, и удерживает выборку пользователя до одного нажатия - и извлекает его только в первый раз, если страница действительно хочет информация CurrentUser.

Таким образом, страница может легко получить текущую информацию о пользователях, таких как:

User user = Global.CurrentUser;
if (user != null) { // unnecessary check if this is a page that users must be authenticated to access
    int age = user.Age; // whatever you need here
}
1 голос
/ 23 апреля 2009

Один из способов - ввести в ваш контроллер класс, который отвечает за получение информации для текущего вошедшего в систему пользователя. Вот как я это сделал. Я создал класс с именем WebUserSession, который реализует интерфейс с именем IUserSession. Затем я просто использую внедрение зависимостей, чтобы внедрить его в контроллер при создании экземпляра контроллера. Я реализовал в своем интерфейсе метод GetCurrentUser, который будет возвращать объект User, который я затем могу использовать в своих действиях при необходимости, передавая его представлению.

using System.Security.Principal;
using System.Web;

public interface IUserSession
{
    User GetCurrentUser();
}

public class WebUserSession : IUserSession
{
    public User GetCurrentUser()
    {
        IIdentity identity = HttpContext.Current.User.Identity;
        if (!identity.IsAuthenticated)
        {
            return null;
        }

        User currentUser = // logic to grab user by identity.Name;
        return currentUser;
    }
}

public class SomeController : Controller
{
    private readonly IUserSession _userSession;

    public SomeController(IUserSession userSession)
    {
        _userSession = userSession;
    }

    public ActionResult Index()
    {
        User user = _userSession.GetCurrentUser();
        return View(user);
    }
}

Как видите, теперь у вас будет доступ для извлечения пользователя, если это необходимо. Конечно, вы можете изменить метод GetCurrentUser, чтобы сначала посмотреть сеанс или другие средства, если хотите, чтобы вы не ходили в базу данных все время.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...