我不明白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;
}
答案 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);
}
}
}