Title- asp.net-mvc5 Auto logout How to make form auto logout after sometime in asp.net-mvc5 and redirect automatically to login page
You need to create a session variable on the Login method.
The session will be created by Session["Userid"]=Userid;. Then you need to create custom attribute to check session timeout.
Steps you need to follow are:
Create a session variable in login() (Post method)
Create a class file in your MVC project.
Copy and paste below code in that file.
public class SessionTimeOutAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Controller controller = filterContext.Controller as Controller;
HttpContext httpContext = HttpContext.Current;
var rd = httpContext.Request.RequestContext.RouteData;
string currentAction = rd.GetRequiredString("action");
string currentController = rd.GetRequiredString("controller");
if (HttpContext.Current.Session["UserId"] == null)
{
filterContext.Result = new RedirectResult("~/Account/Login?ReturnUrl=" + currentController + "/" + currentAction);
return;
}
base.OnActionExecuting(filterContext);
}
}
add [SessionTimeOut] attribute on each controller.
[SessionTimeOut]
public class ControllerName : Controller
{
You should add Statup.cs file.
1. Add Statup Class your project from new item lists.
2. Add following line in ConfigureService.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options => options.EnableEndpointRouting =
false).SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
services.AddAuthorization();
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
// we do this because we trust the network
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
});
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(x =>
{
x.Cookie.Name = "WriteSomeThings";
x.Cookie.SecurePolicy = CookieSecurePolicy.Always;
x.Cookie.SameSite = SameSiteMode.Strict;
x.Cookie.HttpOnly = true;
x.Cookie.IsEssential = true;
x.SlidingExpiration = true;
x.ExpireTimeSpan = TimeSpan.FromHours(8);//For Auto Logout
x.LoginPath = "/User/LogOn";
x.LogoutPath = "/User/LogOff";
x.AccessDeniedPath = "/Home/AccessDenied";
});
}
x.ExpireTimeSpan = TimeSpan.FromHours(8) => This line allow us to logout automatically after 8 hours.
If you need full user management check this video
https://youtu.be/912q3TEF25U
Software development template with role-based user management using ASP.NET MVC 5. Try it for free
Related
In a ASP.NET Core 2 MVC app, I had a custom AuthorizationHandler that redirected blocked users back to the home page.
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IsAllowedIpAddressRequirement requirement)
{
// Cast the context resource
if (context.Resource is AuthorizationFilterContext cxt)
{
// Failed!
cxt.Result = new RedirectToActionResult("Index", "Home", new { msg = "Your auth has failed." });
context.Succeed(requirement);
}
...
}
Since migrating to ASP.NET Core 3.1, the context is an object of class Microsoft.AspNetCore.Routing.RouteEndpoint, which has no Result property.
How can I redirect the user to a specific page?
I had the same problem and to solve it I changed to Filter (IAsyncResourceFilter) instead of Policy.
You can wrap your authorization logic into a policy and then invoke the IAuthorizationService and redirect anywhere/anytime you need.
Example:
public class MySampleActionFilter: IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
//if failed
context.Result = new RedirectToRouteResult(new RouteValueDictonary(new
{
controller = "Your Controller",
action = "Your Action"
}));
}
}
By the way, this is for .net Core 3 and above
Documentation
if you want to user redirect to some page like login page, if user didn't has access, you could following below steps for fix it:
into HandleRequirementAsync method
if (Condition())
{
context.Succeed(requirement);
}
else {
context.Fail();
}
if user did has access, execute context.Succeed(requirement); and if user didn't has access, execute context.Fail();
into startup.cs => ConfigureServices method
services.ConfigureApplicationCookie(options =>
{
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromHours(12);
options.LoginPath = "/Account/Login";
options.AccessDeniedPath = "/Account/AccessDenied";
options.SlidingExpiration = true;
});
in line that we write
options.LoginPath = "/Account/Login";
we appointment users after failing in HandleRequirementAsync method for checking access, being redirected to controller 'home' controller and 'login' actiion.
i'll hope my answer be useful for friends.
I have an asp.net core 2.1 project and I try to use TempData with RedirectToAction but it's always null (without Error)
Here is my ConfigureServices method
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
//services pour l'authentification
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
{
options.LoginPath = "/Login";
});
//services pour session
services.AddSession(options => {
options.IdleTimeout = TimeSpan.FromMinutes(20);
});
//configuer port https
services.AddHttpsRedirection(options => options.HttpsPort = 443);
Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;
ManageDI(services);
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddSessionStateTempDataProvider();
}
I have "app.UseSession();" in my Configure method
and here is my code
[HttpGet]
public async Task< IActionResult> ResetPassword(string query)
{
TempData["test"]= "test";
return RedirectToAction(nameof(Login));
}
[HttpGet]
public IActionResult Login(string returnUrl = null)
{
var b = TempData["test"];
//b is always null when calling ResetPassword action
var model = new Models.Account.LoginModel{
ReturnUrl = returnUrl
};
return View(model);
}
What did I forget please ?
Thanks
It's not entirely clear what the issue is based on the code you've provided, but since you mention that it's null in your ResetPassword action from within your Login action, I'm assuming you're not properly persisting the value.
TempData is just that: temporary data. Once it's been accessed, it is removed. Therefore, when you set b here with its value, that's it - it's gone. If you then try to access it in another action later or even just in the view this action returns, it will be null now.
If you need to get the value, but also keep it around for later, you need to use TempData.Peek:
var b = TempData.Peek("test");
I am setting a session variable in one method and trying to get the session variable value from the another method in a controller but its always getting null:
Here is my code:
public class HomeController : Controller
{
public IActionResult Index()
{
HttpContext.Session.SetString("Test", "Hello!");
var message = HttpContext.Session.GetString("Test");// Here value is getting correctly
return View();
}
public IActionResult About()
{
var message = HttpContext.Session.GetString("Test"); // This value is always getting null here
return View();
}
}
Here is my session configuration in Startup class:
In ConfigureServices() method:
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddDistributedMemoryCache();
services.AddMvc().AddSessionStateTempDataProvider();
services.AddSession(options =>
{
options.Cookie.Name = "TanvirArjel.Session";
options.IdleTimeout = TimeSpan.FromDays(1);
});
In Configure() method:
app.UseSession();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
Very strange and peculiar problem! Any help will be highly appreciated!
For ASP.NET Core 2.1 and 2.2
In the ConfigureServices method of the Startup class, Set options.CheckConsentNeeded = context => false; as follows:
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
Problem solved!
You can also just set Cookie.IsEssential = true as explained here: https://andrewlock.net/session-state-gdpr-and-non-essential-cookies/
There is an overload of services.AddSession() that allows you to configure SessionOptions in your Startup file. You can change various settings such as session timeout, and you can also customise the session cookie. To mark the cookie as essential, set IsEssential to true:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true; // consent required
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddSession(opts =>
{
opts.Cookie.IsEssential = true; // make the session cookie Essential
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
I have had the same issue and tried the following separately and I found that either of them does work for me!
1. options.CheckConsentNeeded = context => false;
2. opts.Cookie.IsEssential = true; // make the session cookie Essential
However, not quite sure though, I think #1 might potentially lead to the breach of GDPR. Hence I would prefer #2.
I tried adding the mentioned lines from Microsoft docs on session it didn't work.
As I see from the code of HttpContext.Session Session can be used in the same request.
So at last, I created one static class as below which helped as Session throughout the application.
public static class SessionHelper
{
private static IDictionary<string, string> Session { get; set; } = new Dictionary<string, string>();
public static void setString(string key, string value)
{
Session[key] = value;
}
public static string getString(string key)
{
return Session.ContainsKey(key) ? Session[key] : string.Empty;
}
}
Usage:
set string in one request
SessionHelper.setString("UserId", "123");
read string in another request
SessionHelper.getString("UserId");
Hope it helps!
I have a bilingual MVC 3 application, I use cookies and session to save "Culture" in Session_start method inside Global.aspx.cs file, but direct after it, the session is null.
This is my code:
protected void Session_Start(object sender, EventArgs e)
{
HttpCookie aCookie = Request.Cookies["MyData"];
if (aCookie == null)
{
Session["MyCulture"] = "de-DE";
aCookie = new HttpCookie("MyData");
//aCookie.Value = Convert.ToString(Session["MyCulture"]);
aCookie["MyLang"] = "de-DE";
aCookie.Expires = System.DateTime.Now.AddDays(21);
Response.Cookies.Add(aCookie);
}
else
{
string s = aCookie["MyLang"];
HttpContext.Current.Session["MyCulture"] = aCookie["MyLang"];
}
}
and second time it goes into the "else clause" because the cookie exists; inside my Filter, when it tries set the culutre, Session["MyCulture"] is null.
public void OnActionExecuting(ActionExecutingContext filterContext)
{
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(HttpContext.Current.Session["MyCulture"].ToString());
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture(HttpContext.Current.Session["MyCulture"].ToString());
}
Why are you using HttpContext.Current in an ASP.NET MVC application? Never use it. That's evil even in classic ASP.NET webforms applications but in ASP.NET MVC it's a disaster that takes all the fun out of this nice web framework.
Also make sure you test whether the value is present in the session before attempting to use it, as I suspect that in your case it's not HttpContext.Current.Session that is null, but HttpContext.Current.Session["MyCulture"]. So:
public void OnActionExecuting(ActionExecutingContext filterContext)
{
var myCulture = filterContext.HttpContext.Session["MyCulture"] as string;
if (!string.IsNullOrEmpty(myCulture))
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo(myCulture);
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(myCulture);
}
}
So maybe the root of your problem is that Session["MyCulture"] is not properly initialized in the Session_Start method.
I am using ASP.NET MVC. I want to redirect to login page when session expires. How can I achieve this? If I am doing an AJAX call to a method in controller then if my session expires in that situation also I want to redirect to login page.
you could do this by 3 ways:
Create a filter to your actions and apply it programming a code in OnActionExecuting (before the action been executed), http://www.asp.net/mvc/tutorials/understanding-action-filters-cs
Create a base class (inheriting from Controller class) and make your controllers inherits from this one. In this class you could overwrite a method called OnActionExecuting, like the filter.
Don't use Session for Authentication, you can use Forms authentication and keep it simple to use, look this: http://weblogs.asp.net/fredriknormen/archive/2008/02/07/asp-net-mvc-framework-using-forms-authentication.aspx
In my opinion, the solution 3 is better than other. I hope it works for you!
because it's possible to copy the security-cookie of the Forms-Authentication use it to simulate a registered user I use the following attribute to bind the authentication to the current session lifetime.
To make the Attribute work you have to set session["user"] = MyUser on login and call session.abandom() on logout.
I don't know if the redirect works with ajax calls - that's something you have to try.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class CheckUserSessionAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpSessionStateBase session = filterContext.HttpContext.Session;
var user = session["User"];
if (((user == null) && (!session.IsNewSession)) || (session.IsNewSession))
{
//send them off to the login page
var url = new UrlHelper(filterContext.RequestContext);
var loginUrl = url.Content("~/Account/LogOff");
session.RemoveAll();
session.Clear();
session.Abandon();
filterContext.HttpContext.Response.Redirect(loginUrl, true);
}
}
}
This answers is heavily based on Michaels except it works ;-)
I changed it to take a delegate for checking if the session has ended so it can work in different apps which might have different ways of determining this and also the login page might be different in other apps. In the Global.asax.cs Application_Start() the code I have in my app is
CheckUserSessionAttribute.CheckSessionAlive = session => (session.GetUser() != null);
CheckUserSessionAttribute.LoginUrl = "~/Account/Login";
Then the attribute class is as follows
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class CheckUserSessionAttribute : ActionFilterAttribute
{
public static String LoginUrl { get; set; }
public delegate bool CheckSessionDelegate(HttpSessionStateBase session);
public static CheckSessionDelegate CheckSessionAlive;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpSessionStateBase session = filterContext.HttpContext.Session;
if ((CheckSessionAlive == null) || (CheckSessionAlive(session)))
return;
//send them off to the login page
var url = new UrlHelper(filterContext.RequestContext);
var loginUrl = url.Content(LoginUrl);
session.RemoveAll();
session.Clear();
session.Abandon();
filterContext.HttpContext.Response.StatusCode = 403;
filterContext.HttpContext.Response.Redirect(loginUrl, false);
filterContext.Result = new EmptyResult();
}
}
From your controller just add the [CheckUserSession] attribute above the class or the individual actions.
Another plausible solution could be found in here:
Overriding Controller Methods for session Timeout handling