FormsAuthentication Uses The Same Ticket Throughout Browsers (on the same PC)?
I do not understand what's going on with FormsAuthentication. When I first turn on my PC and start working on my project, everytime I try to login, I get an error telling me that the queried username (nickname in my case) is not found the sequence. I check its value while debugging, it turns out it's a null string (""). Then if I stop debugging then start it again, I get logged in normally and it picks up the right username.
Moreover, if I try to login with another user from another browser, the same thing happens but eventually it picks up the same user that was logged in using the same browser! Does FormsAuthentication use the same ticket in all browsers, for all users? Is there anything I can do about it? Or could it be that I'm doing something wrong here...?
Here's my code:
[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;
}
The method above is in a helper class (which takes an instance of HttpContext - using StructureMap). It keeps returning the user with nickname J.Smith
even if I logged in with another user. And the funny thing is that it then displays the correctly logged in user using the Summary
ActionMethod (see below).
[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);
}
This method displays a summary of all the user's info including their bids, listings, new messages... etc. This actually works correctly (in most cases). But the problem is with the GetUserFromSession()
method which is messing everything up.
public ActionResult SignOut()
{
FormsAuthentication.SignOut();
return RedirectToAction("Index", "Home");
}
Is that all I need to do to sign the user out and delete their cookie/session or whatever FormsAuthentication does to manage sessions?
Note: I am not using the built-in Membership API and I do not want to use it.
So, is there anything I can do to fix this mess?
UPDATE:
StructureMap configuration:
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&l开发者_如何学运维t;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;
}
You could write a HttpContext provider class (interface) that just returns the current HttpContext.Current instance.
using System.Web;
interface IHttpContextProvider
{
HttpContextBase HttpContext { get; }
}
public class HttpContextProvider : IHttpContextProvider
{
HttpContextBase HttpContext
{
get
{
return new HttpContextWrapper(System.Web.HttpContext.Current);
}
}
}
It sounds like the scope fo the _httpContext
instance being maintained/created by StrucutureMap is incorrect. Here's some more information on scope--I'd be happy to look into it further if you want to post your StrucutureMap registration code.
精彩评论