I'm not use FormsAuthenticatio.
When the user Login, I will save the user info to on session like:
HttpContext.Current.Session["UserId"] = model.Id;
HttpContext.Current.Session["Name"] = model.Name
But How I set the session expired time use code?
Maybe only for 30 minute, Maybe User select "Remember Me" then save it 24 hour.
Second question is : If I'm already set it expired time on web.config like:
<sessionState mode="InProc" timeout="30" />
Then How about the priority ? config first or code first?
You can set session in code, global.asax on session_start event using this.
Session.Timeout = 24*60 ;
I have checked in code that, setting session in code like above override that in web.config. So the above has more priority and this will be used and web.config's value will be discarded.
if the user ticks "Remember Me", just add a random guid to a database of active users and give them a cookie with the same guid. when the user comes back without a valid session, check for the cookie and search the database for the guid. if valid, the user is signed in
Related
I am creating a website, and I'm not sure how to use sessions with cookies.
When sessions timeout, I want to show the username and time of the user; for e.g., username stored in cookies and session. When sessions timeout the username must be retrived from the cookies.
Lets put things in perspective first.
A session is the session a user is experiencing when he is using the website.
How it works is basically a user starts a session with the web server, the web server then gives it a key of the session and sets a timeout for the session which are stored as a cookie.
Since this process is automatic and you can only configure it in web.config (unless you are asp.net core vNext, which I doubt) with sessionState https://msdn.microsoft.com/en-us/library/h6bb9cz9%28v=vs.80%29.aspx
A normal HttpCookie on another hand is something you set on your Response object and can give it a specific expiration date like this:
HttpCookie myCookie = new HttpCookie("MyTestCookie");
DateTime now = DateTime.Now;
// Set the cookie value.
myCookie.Value = now.ToString();
// Set the cookie expiration date.
myCookie.Expires = now.AddMinutes(1);
// Add the cookie.
Response.Cookies.Add(myCookie);
Which suits your needs more likely.
If you want more information about sessions expiration I'd also suggest you check out http://www.hanselman.com/blog/TroubleshootingExpiredASPNETSessionStateAndYourOptions.aspx
I have an MVC4 single application page. In the log-in page there are 3 fields: user, password and "remember me" checkbox.
The C# login code is this:
if (WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
return Json(new { success = true, redirect = returnUrl });
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
I want to do this:
If a user logs in with "remember me" true - The cookie will stay until the user logs off.
If the user logs in with "remember me" false - The cookie will expire after 3 hours.
In web.config I have this code:
<authentication mode="Forms">
<forms loginUrl="~/" timeout="180" cookieless="UseCookies" slidingExpiration="false" />
</authentication>
<sessionState timeout="180" />
The problem is when the user doesn't touch the page for a short time (10-30 mins usually), and then the user tries to do something in the page - there is an error
"Authorization has been denied for this request."
(Although sessionStation is more than 30 minutes!)
After the user refresh the page - if the cookie hasn't expired yet - everything works fine. But of course I don't want to make the user refresh the page every 15 minutes or so, it's a single-page-application.
So, I tried to change slidingExpiration to "true" and create a ping (with ajax) every 17 minutes and it really stopped the session expiration and the annoying message - but the cookie didn't expired after 3 hours (I logged in with remember me 'false')!
What can I do?
Right click your application pool from IIS management console and look for "Idle time-out(minutes)".
You can adjust the setting to 0 (zero) which effectively disables the timeout so that the application pool will never shut down due to being idle.
I would double check your IIS settings. See what your App Pool Idle Timeout value is set to. By default it's 20 minutes. When the App Pool goes idle (no users accessing the app pool) for twenty minutes, you will loose session state (All data stored in the session will be cleared).
With more users this problem would work itself out, but presuming you are the only person testing, increasing this value to something greater than 180 minutes will prevent the timeout, or you could set the value to zero to disable the app pool idle timeout altogether.
See this answer for information on checking your app pool timeout in IIS Express... https://stackoverflow.com/a/10222419/386856
Do note that a dead app pool can take several seconds to re-spawn. It may be beneficial to increase this value anyways. This will prevent users from having an extremely slow experience if they happen to be the person that's unlucky enough to have to wait for the app pool to restart.
Update
To allow for a change in timeout for users who don't click remember me, you can create a custom attribute or you could modify the FormsAuthentication timeout via C#. Here are good references on setting the timeout via code. https://msdn.microsoft.com/en-us/library/system.web.configuration.formsauthenticationconfiguration.timeout%28v=vs.110%29.aspx and https://msdn.microsoft.com/en-us/library/system.web.configuration.formsauthenticationconfiguration(v=vs.110).aspx If you want the timeout to expire right at 3 hours, even if the user has activity be sure slidingExpiration is false in your web config. If you want the timeout to expire 3 hours after the user's last activity be sure slidingExpiration is true. So before you set the cookie try something like the following (Be sure to check the OpenWebConfiguration path):
System.Configuration.Configuration configuration = WebConfigurationManager.OpenWebConfiguration("/aspnetTest");
AuthenticationSection authenticationSection = (AuthenticationSection)configuration.GetSection("system.web/authentication");
FormsAuthenticationConfiguration formsAuthentication = authenticationSection.Forms;
formsAuthentication.Timeout = System.TimeSpan.FromHours(3);
formsAuthentication.SlidingExpiration = true;
I solved this by just creating my own encrypted cookie which will persist the user's session if present. In an action filter attribute, check if the user's session is expired, check for this cookie. If the cookie exists, verify the information and reestablish the session. If the user doesn't have a session, doesn't have a cookie, or the encrypted credentials are incorrect, redirect the user to the login page. Since everything is handled in the code, there is no guess work on the server settings.
On login with remember me checked:
if (RememberMe ?? false)
{
var authCookie = new HttpCookie(Config.AuthorizationCookie);
authCookie.Values.Add("ID", Crypto.EncryptStringAES(UserSession.Current.Account.ID.ToString(), Config.SharedSecret));
authCookie.Expires = DateTime.Now.AddDays(30);
AuthorizationCookie = authCookie;
}
Response.AppendCookie(AuthorizationCookie);
On page visit without session (done inside an attribute attached to necessary controllers and actions):
_account = UserSession.Current.Account;
// check if there is currently an account in the session
if(_account == null)
{
// check the user authorization cookie for a user id
HttpCookie authCookie = HttpContext.Current.Request.Cookies[Config.AuthorizationCookie] ?? new HttpCookie(Config.AuthorizationCookie);
if (authCookie.HasKeys && !String.IsNullOrEmpty(authCookie["ID"]))
{
// decrypt the user id for database lookup
_userID = Crypto.DecryptStringAES(authCookie.Values["ID"], Config.SharedSecret);
}
}
Re-establish the session if necessary (done inside a database connection)
// called within a database connection's using statement
protected override void Query(DatabaseContext db)
{
// check the database for the user account
if(_account == null && !String.IsNullOrEmpty(_userID))
{
int tempID;
int? id;
id = int.TryParse(_userID, out tempID) ? tempID : (int?)null;
if(id.HasValue)
{
_sessionRestored = true;
_account = db.User.Find(id);
if(_account != null)
{
_account.LastLogon = DateTime.UtcNow;
db.SaveChanges();
}
}
}
}
Finally restore the session:
if (_account != null)
{
// set the current account
UserSession.Current.Account = _account;
if(_sessionRestored)
{
UserSession.Current.Refresh();
}
}
Your code may look a bit different but that is the crux of how I did it.
I need to sign out a user when the user closed the tab or browser, how do I do that in ASP.NET MVC?
There are a few things you can do to make sure the user is signed out when the browser is closed, but it depends on how you're setting the FormsAuthentication cookie:
Use Cookieless=True.
Set a FormsAuthenticationTicket to not be persistent
Use FormsAuthentication.SetAuthCookie to set Persistence to false
Use a JavaScript approach to remove the cookie on window.unload.
Cookieless=True approach:
<system.web>
<authentication mode="Forms">
<forms loginUrl="/Account/Login"
protection="All"
cookieless="true" //set to true
</authentication>
</system.web>
This appends the cookie value to the querystring in each request. The problem with this approach is it's not very secure and it messes with SEO. If a user sends anyone the URL they're using, that person can log in as the original user (probably not what you want). As far as 'messing with SEO', it causes the same page to look different to a googlebot based on what URL is passed in. Each QueryString change makes it a new URL, and if anyone uses this for posting a link; it will dilute the search results for a given actual URL.
FormsAuthenticationTicket Approach
When you set an Authentication cookie for the user, set Persistent to False.
If you're doing this in the FormsAuthentication.SetAuthCookie, this is default. If you use the FormsAuthenticationTicket class, you have to specify the cookie expiration.
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1, //version
"blah", //Cookie Name
);
FormsAuthentication.SetAuthCookie() Approach
By default, if you don't set persistent, the authentication cookie will expire at the end of the session (when the user closes the browser).
FormsAuthentication.SetAuthCookie("CookieValue", false); //second argument is persistent'
JavaScript approach:
There are no foolproof methods; all you can do is set the cookie expiration date to before now and hope the user's browser co-operates. If you really, really, really, want the cookie gone, you can always try a JavaScript approach, but that won't work if the user has JavaScript disabled.
window.addEventListener('unload', function(event) {
document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
});
Other caveats
It also matters which browser you use. Chrome has the ability to run in the background, and that keeps Session Cookies around until their timeout is hit -- they are not dropped when the browser is closed (I found this out the hard way).
I want to add a "keep me logged in" option to my custom login control.
This is how I'm currently using the session:
I'm saving and reading values from HttpContext.Current.Session["key"] manually. Works fine.
Relevant parts of web.config:
<sessionState mode="StateServer" useHostingIdentity="true" cookieless="false" timeout="120" stateConnectionString="tcpip=127.0.0.1:42424" />
<authentication mode="Forms">
<forms loginUrl="/login" name="AuthCookie" timeout="120" slidingExpiration="true" path="/" />
</authentication>
<authorization>
<allow users="*" />
</authorization>
As you can see, the default duration of a session is 120 minutes.
"Logout":
Session.Clear();
Session.Abandon();
Through a custom login control with textboxes, I grant access to a member area. (I don't use System.Web.Security.FormsAuthentication)
After entering valid credentials and a checked checkbox "keep logged in", I want to increase the duration of the already active session to ~30 days.
So far I've found solutions like
FormsAuthenticationTicket fat = new FormsAuthenticationTicket(1, "username", DateTime.Now, DateTime.Now.AddMinutes(1), false, "username");
string encTicket = FormsAuthentication.Encrypt(fat);
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket) { Expires = fat.Expiration });
which don't work, because System.Web.Security.FormsAuthentication.Timeout is still at 120 minutes.
The same goes for setting
Session.Timeout = 666;
Any suggestions?
You can't really approach it this way. You can't persist a session over days - it's just not going to scale well.
What most people do is provide a means for automatic login, so that when their session expires, they are seamlessly logged back in on the next action/reload. Most people do this with a cookie that contains a unique hash, which is checked at the server. If you want the person to be logged in for 30 days, you just set the cookie to expire in 30 days time.
I decided to give a short summary how I ended up doing it, because #David Haney asked me to:
I added a column to my usertable, which contains a GUID that is used for "relogging in" / giving credentials again. That GUID is created upon login and stored in the database.
It's also stored as an ecrypted value in a cookie. (My site doesn't use SSL)
Added to Login routine (if a user checked the "remeber me" checkbox):
HttpCookie aCookie = new HttpCookie("Session");
Guid sessionGuid = // Buisiness layer call to generate value
String sessionID = sessionGuid.ToString();
aCookie.Value = Helper.Protect(sessionID, "sessionID");
aCookie.Expires = DateTime.Now.AddDays(30);
Response.Cookies.Add(aCookie);
where Helper.Protect and Helper.Unprotect are used from here How to use MachineKey.Protect for a cookie? to store an encrypted and MAC signed value in a cookie.
Relogging is done by having every content page inherit from a class, that implements that logic and inherits from System.Web.UI.Page.
public class BasePage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (Request.Cookies["Session"] != null && !CustomIsLoggedInCheckMethod)
{
String unprotected = Helper.Unprotect(Request.Cookies["Session"].Value, "sessionID");
Guid sessionID = Guid.Parse(unprotected);
// Calls to buisiness layer to get the user, set sessions values et cetera
}
}
}
If a user was banned after the last session or logs out, the cookie value expiration date will be set to a date in the past:
HttpCookie myCookie = new HttpCookie("Session");
myCookie.Expires = DateTime.Now.AddDays(-1d);
Response.Cookies.Add(myCookie);
Edit:
Ah I forgot to mention this. I've also added a notification bar, that tells the user that he has been logged back in. It's based on http://blog.grio.com/2012/11/a-copypaste-ble-jquery-notification-bar.html
See Demo
On my website
Filling form before login save data in Session
Login Using Linkedin ID
after login at Pageload taking data from session then inserting into SQL data base
My problem is some times I am getting session and other times I am not getting session (Session Lost) ( mostly when 3-4 people testing at the same time... 2-3 get session and 1-2 not getting session)
Can any one tell me what is the problem? How can I solve this problem?
Any another way to do this task?
Stroing in session before login
Session["sesObjFundRaiseSeek"] = objFundRaiseSeek;
Getting after login
if (Session["sesObjSellSeekBL"] != null)
{
clsSellSeekBL ObjSellSeekBL = (clsSellSeekBL)Session["sesObjSellSeekBL"];
}
Is it a problem with your sessions timing out after a very short period of time? You can input the default session timeout within the web.config. This is done right under system.web. Here is an example where 480 is the number of minutes:
<sessionState timeout="480"></sessionState>
For more information: http://msdn.microsoft.com/en-us/library/h6bb9cz9(v=vs.71).aspx
An alternate solution is to use Cookies. I would recommend using Cookies to store user state information. Since Cookies are stored on the users computer, it is easier to configure:
I set to expiration date to 100000 days later in the example below:
HttpCookie myCookie = new HttpCookie("sesObjSellSeekBL");
myCookie.Value = Convert.ToString(user_id); //store the user id here at the very least
myCookie.Expires = DateTime.Now.AddDays(100000d);
Response.Cookies.Add(myCookie);
Here is how you check your Cookie:
if (Request.Cookies["sesObjSellSeekBL"] != null)
Here is how you log the user out:
HttpCookie myCookie = new HttpCookie("sesObjSellSeekBL");
myCookie.Expires = DateTime.Now.AddDays(-1d);
Response.Cookies.Add(myCookie);