FormsAuthentication在整个浏览器中使用相同的票证(在同一台PC上)?

时间:2011-04-24 09:56:09

标签: asp.net asp.net-mvc asp.net-mvc-3 forms-authentication authorization

我不明白FormsAuthentication发生了什么。当我第一次打开我的电脑并开始处理我的项目时,每次我尝试登录时,都会收到一个错误,告诉我查询的用户名(在我的情况下是昵称)没有找到序列。我在调试时检查它的值,结果发现它是一个空字符串(“”)。然后,如果我停止调试然后再次启动它,我会正常登录并且它会选择正确的用户名。

此外,如果我尝试从另一个浏览器中与另一个用户登录,则会发生同样的事情,但最终它会选择使用相同浏览器登录的同一用户!对于所有用户,FormsAuthentication是否在所有浏览器中使用相同的票证?我能做些什么吗?或者可能是我在这里做错了什么......?

这是我的代码:

    [HttpPost]
    public ActionResult Login(LoginViewModel dto)
    {  
        bool flag = false;
        if (ModelState.IsValid)
        {
            if (_userService.AuthenticateUser(dto.Email, dto.Password, false))
            {
                var user = _userService.GetUserByEmail(dto.Email);

                flag = true;

                FormsAuthentication.SetAuthCookie(user.Nickname, dto.RememberMe);
            }
        }
        if (flag)
        {
            return RedirectToAction("Index", "Home");
        }
        else
        {
            ViewData.Add("InvalidLogin", "The login info you provided were incorrect.");
            return PartialView(dto);
        }
    }

    public User GetUserFromSession(bool withAllInfo)
    {
        string nickname = _httpContext.User.Identity.Name;
        IsNotNull(nickname, "session user nickname");
        var user = _userService.GetUserByNickname(nickname, withAllInfo);
        return user;
    }

    public User GetUserFromSession(string nickname, bool withAllInfo)
    {
        if (string.IsNullOrEmpty(nickname))
            return GetUserFromSession(withAllInfo);

        var user = _userService.GetUserByNickname(nickname, withAllInfo);
        return user;
    }

上面的方法是在一个帮助器类中(它使用了一个HttpContext实例 - 使用StructureMap)。即使我与其他用户登录,它仍然以昵称J.Smith返回用户。有趣的是它然后使用Summary ActionMethod显示正确登录的用户(见下文)。

    [Authorize]
    public ActionResult Summary()
    {
        var nickname = this.HttpContext.User.Identity.Name;
        var user = _helper.GetUserFromSession(nickname, true);
        var viewModel = Mapper.Map<User, UserInfoSummaryViewModel>(user);
        return PartialView(viewModel);
    }

此方法显示所有用户信息的摘要,包括其出价,列表,新消息......等。这实际上可以正常工作(在大多数情况下)。但问题在于GetUserFromSession()方法,这会弄乱一切。

    public ActionResult SignOut()
    {
        FormsAuthentication.SignOut();
        return RedirectToAction("Index", "Home");
    }

我需要做的就是签署用户并删除他们的cookie /会话或任何FormsAuthentication管理会话的工作吗?

注意:我没有使用内置的Membership API,我也不想使用它。

那么,有什么办法可以解决这个问题吗?

更新

StructureMap配置:

    private static IContainer ConfigureStructureMap()
    {

        ObjectFactory.Configure(x =>
                            {
                                x.For<IDatabaseFactory>().Use<EfDatabaseFactory>();
                                x.For<IUnitOfWork>().Use<UnitOfWork>();
                                x.For(typeof (IRepository<>)).Use(typeof (BaseRepository<>));
                                x.For<IGenericMethodsRepository>().Use<GenericMethodsRepository>();
                                x.For<IUserService>().Use<UsersManager>();
                                x.For<IBiddingService>().Use<BiddingService>();
                                x.For<ISearchService>().Use<SearchService>();
                                x.For<IFaqService>().Use<FaqService>();
                                x.For<IItemsService>().Use<ItemsService>();
                                x.For<IPrivateMessagingService>().Use<PrivateMessagingService>();
                                x.For<IStaticQueriesService>().Use<StaticQueriesService>();
                                x.For<ICommentingService>().Use<CommentingService>();
                                x.For<ICategoryService>().Use<CategoryService>();
                                x.For<IHelper>().Use<Helper>();
                                x.For<HttpContext>().Use(HttpContext.Current);

            x.For(typeof(Validator<>)).Use(typeof(NullValidator<>));

            x.For<Validator<Rating>>().Use<RatingValidator>();
            x.For<Validator<TopLevelCategory>>().Use<TopLevelCategoryValidator>();
        });

        Func<Type, IValidator> validatorFactory = type =>
        {
            var valType = typeof(Validator<>).MakeGenericType(type);
            return (IValidator)ObjectFactory.GetInstance(valType);
        };

        ObjectFactory.Configure(x => x.For<IValidationProvider>().Use(() => new ValidationProvider(validatorFactory)));
        return ObjectFactory.Container;
    }

2 个答案:

答案 0 :(得分:0)

听起来,StrucutureMap维护/创建的_httpContext实例的范围不正确。 Here's有关范围的更多信息 - 如果您想发布StrucutureMap注册码,我将很乐意进一步研究。

答案 1 :(得分:0)

您可以编写一个只返回当前HttpContext.Current实例的HttpContext提供程序类(接口)。

using System.Web;

interface IHttpContextProvider
{
    HttpContextBase HttpContext { get; }
}

public class HttpContextProvider : IHttpContextProvider
{
    HttpContextBase HttpContext
    {
        get
        {
            return new HttpContextWrapper(System.Web.HttpContext.Current);
        }
    }
}