我使用asp.net Forms身份验证来要求用户在访问特定页面时登录。我希望用户在不活动5分钟后再次登录,但无论我在web.config中的表单部分的超时值中放置了什么,用户仅在会话状态到期后才会启动。表单身份验证超时被忽略
一个我一直在尝试,测试包括以下配置:
<system.web>
<sessionState timeout="1" />
<authentication mode="Forms">
<forms loginUrl="~/authentication" timeout="2" slidingExpiration="true"/>
</authentication>
</system.web>
如果我登录并保持空闲一分钟,我问,如果我刷新页面,重新登录。但是,我的印象是,我应该能够继续工作,直到表单身份验证超时过期。我明白,在1分钟的时间内,对于slidingexpiration设置来更新我的cookie已经太晚了,但我应该在cookie实际到期之前还有一分钟。
如果我删除Sessiontate超时部分,我不会在两分钟后通过登录。在我被要求重新登录之前,需要很长时间(大概30分钟)。这对我来说听起来像只有在sessionState过期时才会被要求重新登录。
我在这里错过了什么吗?
下面是涉及的控制器和方法的基本布局。首先,用户试图去招聘页面:
public class HireController : Controller
{
[Authorize]
public ActionResult Recruiter()
{
//do stuff after we've been authorized to access this page
}
}
因为用户需要授权他们将被重定向到登录页面,认证控制器:
public class AuthenticationController : BaseAuthenticationController
{
private readonly IAuthenticationService AuthenticationService;
public AuthenticationController(IAuthenticationService authService)
: base(authService)
{
AuthenticationService = authService;
}
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index(string returnUrl)
{
var special= false;
return View("~/Views/Login/Login.cshtml", new LoginModel(special) { ReturnUrl = returnUrl });
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(LoginCredentials credentials, string returnUrl)
{
try
{
if (!ModelState.IsValid)
{
throw new ApplicationException(GeneralError);
}
base.DoLogin(credentials.Username, credentials.Password);
}
catch (Exception ex)
{
string message = (ex is ApplicationException) ? ex.Message : GeneralError;
ModelState.AddModelError("", message);
return View("~/Views/Login/Login.cshtml", new LoginModel { Username = credentials.Username, ReturnUrl = returnUrl });
}
return RedirectToLocal(returnUrl);
}
private ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
if (User.Identity != null && User.Identity.IsAuthenticated)
{
return RedirectToAction("Recruiter", "Hire");
}
return RedirectToAction("Recruiter", "Hire");
}
}
这里是BaseAuthenticationController类:
public class BaseAuthenticationController : Controller
{
private readonly IAuthenticationService AuthenticationService;
protected const string GeneralError = "Login failure please try again";
public BaseAuthenticationController(IAuthenticationService authService)
{
AuthenticationService = authService;
}
public void DoLogin(string username, string password)
{
AuthenticationService.Login(username, password);
}
}
下面是具体的IAuthenticationService类:
public class WebAuthenticationService : IAuthenticationService
{
private const string InvalidError = "Invalid User Credentials Please try again";
private const string LockoutError = "You have been locked out of the Hiring Center. You will receive an email shortly once your password has been reset.";
readonly string uri = ConfigurationManager.AppSettings["HiringLoginApiBaseUrl"];
private readonly ISecurityContext SecurityContext;
public WebAuthenticationService(ISecurityContext securityContext)
{
SecurityContext = securityContext;
}
private LoginResult GetUserLogin(string username, string password)
{
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(uri);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("username", username),
new KeyValuePair<string, string>("password", password)
});
var postResult = httpClient.PostAsync("/api/Login/Post", content).Result;
var loginResult = postResult.Content.ReadAsAsync<LoginResult>().Result;
return loginResult;
}
}
public MembershipProvider AuthenticationProvider
{
get { return Membership.Provider; }
}
public void Login(string userName, string password)
{
var loginResult = this.GetUserLogin(userName, password);
if (!loginResult.IsValid)
{
throw new ApplicationException(InvalidError);
}
if (loginResult.IsLockedOut)
{
throw new ApplicationException(LockoutError);
}
// Maintain the location
IUser current = SecurityContext.Current;
SecurityContext.SetCurrent(User.CreateAuthorized(userName, current.Location, current.Preferences));
FormsAuthentication.SetAuthCookie(userName, false);
}
}
我不上点以下行的是什么太清楚是在WebAuthenticationService类:是指
SecurityContext.SetCurrent(User.CreateAuthorized(userName, current.Location, current.Preferences));
的setCurrent()方法如下:
public class HttpSecurityContext : ISecurityContext
{
public static string SECURITY_CONTEXT_KEY = "SECURITY_CONTEXT";
public IUser Current
{
get
{
IUser user = HttpContext.Current.User as IUser;
if (user == null)
{
throw new ApplicationException("Context user is invalid;");
}
return user;
}
}
public void SetCurrent(IUser user)
{
HttpContext.Current.User = user;
}
}
Web.Config会员供应商:
<membership>
<providers>
<clear />
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=asdfasf" connectionStringName="mydb" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="3" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" applicationName="/" />
</providers>
</membership>
什么是查看在应用程序的登录名?通常情况下,开发人员在config表单元素中有一个名为'Login'的视图,在这种情况下loginUrl =“〜/ authentication/Login”。 – Sunil
视图本身被称为Login.cshtml。 'loginUrl =“〜/ authentication”'设置触发认证控制器中的Index方法,该方法在检查ModelState是否有效后又将用户带到Login.cshtml视图。登录逻辑似乎大部分工作正常。唯一关闭的是用户注销并且被要求重新输入其凭据的时间间隔。 – Bruno
可能你应该尝试'loginUrl =“〜/ authentication/Login”'。我不知道你的应用程序需求是什么,但是为了将用户重定向到登录页面,应该不需要检查ModelState。但是,当您使用HttpPost调用Login操作时,即用户提交他/她的凭据时,则需要检查ModelState。所以我猜测,你没有正确连接认证部分。 – Sunil