ASP.Net MVC 3 Redirect UnAuthorized User not to loginUrl - asp.net-mvc-3

i have a project using ASP.Net MVC3 and using membership for roles. i use authorize in every controller.
eg:
[Authorize(Roles = "Administrator")]
public ActionResult Index(string q, int i)
{
return View(model);
}
if someone doesnt have role for administrator, then it will redirect to login page by default. how to change it,so it will redirect into Views/Shared/UnAuthorize.cshtml ? or maybe if someone doesnt have role for administrator, it will show message box (alert) ?
thanks in advance.

i solved my problem. i only do this :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
public class MyAuthorize : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
//you can change to any controller or html page.
filterContext.Result = new RedirectResult("/cpanel/roles/unauthorize");
}
}
and apply MyAuthorize to class or action:
[MyAuthorize]
public class AdminController :Controller
{
}
thats it.

Just change the page that have to be shown in the web.config (check that the route exists)
<authentication mode="Forms">
<forms loginUrl="~/UnAuthorize" timeout="2880" />
</authentication>
If you, instead, want to redirect to a specific path for every roles you can extend the AuthorizeAttribute with your own. Something like this (not tested, I write this to give you an idea)
public class CheckAuthorize : ActionFilterAttribute
{
public Roles[] Roles { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//Your code to get the user
var user = ((ControllerBase)filterContext.Controller).GetUser();
if (user != null)
{
foreach (Role role in Roles)
{
if (role == user.Role)
return;
}
}
RouteValueDictionary redirectTargetDictionary = new RouteValueDictionary();
if user.Role==Role.Administrator
{
redirectTargetDictionary.Add("action", "Unauthorized");
redirectTargetDictionary.Add("controller", "Home");
}
else
{
redirectTargetDictionary.Add("action", "Logon");
redirectTargetDictionary.Add("controller", "Home");
}
filterContext.Result = new RedirectToRouteResult(redirectTargetDictionary);
}
}

Well, you can inherit from AuthorizeAttribute and override HandleUnauthorizedRequest which is responsible for redirection of unauhorized/unauthenticated requests. i think this question will be helpful to you

My own version, based on ntep vodka's:
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if(IsUserAuthenticated(filterContext.HttpContext))
{
filterContext.Result = new RedirectResult("/Account/InvalidRole");
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
private bool IsUserAuthenticated(HttpContextBase context)
{
return context.User != null && context.User.Identity != null && context.User.Identity.IsAuthenticated;
}
}
This way I get standard redirect to login page for not authenticated users, and custom redirect for users that are authenticated but don't have the appropriate role for the action.

The code below helped and here is the reference in stackoverflow
ASP.NET MVC 4 custom Authorize attribute - How to redirect unauthorized users to error page?
public class CustomAuthorize: AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if(!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
base.HandleUnauthorizedRequest(filterContext);
}
else
{
filterContext.Result = new RedirectToRouteResult(new
RouteValueDictionary(new{ controller = "Error", action = "AccessDenied" }));
}
}
}

I use this method and it is very easy to implement.
Securing Asp.net MVC3
Change your default route to logon page in global.asax

Related

How to redirect user after login Web API?

If my user encounters a controller with my attribute [CustomAuthorize], he is redirected to the login page where he gets his JWT token. But on successful login I want to redirect him to the place where he initially wanted to be(the URL he wrote before was redirected to login page). what's the best way to save the path?
That's my CustomAuthorizeAttribute:
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.Result = new RedirectResult("~/Login");
return;
}
if (filterContext.Result is HttpUnauthorizedResult)
{
filterContext.Result = new RedirectResult("~/Login");
return;
}
}
}
In other words, how to know from which request the user came from?
I'be decided to write pass a parameter to Login Controller like this
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
var values = new RouteValueDictionary(new
{
controller = "Login",
RequestedAddress = filterContext.RequestContext.RouteData.Values.Values.First()
});
filterContext.Result = new RedirectToRouteResult(values);
return;
}
if (filterContext.Result is HttpUnauthorizedResult)
{
filterContext.Result = new RedirectResult("~/Login");
return;
}
}
And then to get it like this
public class LoginController : Controller
{
public ActionResult Index(String RequestedAddress)
{
return View();
}
}

Redirect to Login on session expiry in MVC

How I can redirect to Login.cshtml from session_end of Global.asax on session expiry.
Response.redirect() not working there.
Please comment on it.
try this may be you will able to check the session is in process or expire
Check this
Answer is given here
check also
Here is the Class which overrides ActionFilterAttribute.
public class SessionExpireAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpContext ctx = HttpContext.Current;
// check sessions here
if( HttpContext.Current.Session["username"] == null )
{
filterContext.Result = new RedirectResult("~/Login/Index");
return;
}
base.OnActionExecuting(filterContext);
}
}
Then in action just add this attribute as shown :
[SessionExpire]
public ActionResult Index()
{
return Index();
}
Or Just add attribute only one time as :
[SessionExpire]
public class LoginController : Controller
{
public ActionResult Index()
{
return Index();
}
}

Action Filter to check Session MVC3

I want to create some custom Filters in my application
After successful login i keep logged in user details in a session and want to check the session is expired or not ( If session expired i want to redirect to login page) and i need a filter for this.
public class MyActionFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
SchoolApp.ViewModels.CurrentSessionModel model=(SchoolApp.ViewModels.CurrentSessionModel)HttpContext.Current.Session["mySession"];
if (model == null)
{
//Redirect to Login page
}
else
{
base.OnActionExecuting(filterContext);
}
}
}
But the problem is this will fire for every rquests even while loading Login page . So how can i make a useful filter control that check for session
Looks like you're trying to do wrong things there. Check your web.config file - it should have section like:
<authentication mode="Forms">
<forms loginUrl="http://www.your_domain.com/login" name="cookie_name" defaultUrl="default_url" domain="your_domain" enableCrossAppRedirects="true" protection="All" slidingExpiration="true" cookieless="UseCookies" timeout="1440" path="/" />
</authentication>
If your session is expired (cookie with cookie_name non exists anymore) - user will be automatically redirected to loginUrl
If you still want to use filters - there's solution that allows you to exclude global filter for some controllers/actions:
assuming you have method in global.asax.cs:
private static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
IFilterProvider[] providers = FilterProviders.Providers.ToArray();
FilterProviders.Providers.Clear();
FilterProviders.Providers.Add(new ExcludeFilterProvider(providers));
filters.Add(DependencyResolver.Current.GetService<MyFilter>(), 2); // add your global filters here
}
Call it in your global.asax.cs:
RegisterGlobalFilters(GlobalFilters.Filters);
Filter provider class will look like:
public class ExcludeFilterProvider : IFilterProvider
{
private readonly FilterProviderCollection _filterProviders;
public ExcludeFilterProvider(IFilterProvider[] filters)
{
_filterProviders = new FilterProviderCollection(filters);
}
public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
Filter[] filters = _filterProviders.GetFilters(controllerContext, actionDescriptor).ToArray();
if (filters.Select(f => f.Instance).OfType<OverrideExcludeFilter>().Any())
return filters;
IEnumerable<ExcludeFilterAttribute> excludeFilters = (from f in filters where f.Instance is ExcludeFilterAttribute select f.Instance as ExcludeFilterAttribute);
var excludeFilterAttributes = excludeFilters as ExcludeFilterAttribute[] ?? excludeFilters.ToArray();
if (excludeFilterAttributes.FirstOrDefault(f => f.AllFilters) != null)
{
return new Collection<Filter>();
}
var filterTypesToRemove = excludeFilterAttributes.SelectMany(excludeFilter => excludeFilter.FilterTypes);
IEnumerable<Filter> res = (from filter in filters where !filterTypesToRemove.Contains(filter.Instance.GetType()) select filter);
return res;
}
}
ExcludeFilter attribute class:
public class ExcludeFilterAttribute : FilterAttribute
{
private readonly Type[] _filterType;
public ExcludeFilterAttribute(bool allFilters)
{
AllFilters = allFilters;
}
public ExcludeFilterAttribute(params Type[] filterType)
{
_filterType = filterType;
}
/// <summary>
/// exclude all filters
/// </summary>
public bool AllFilters { get; private set; }
public Type[] FilterTypes
{
get
{
return _filterType;
}
}
}
And usage sample:
[ExcludeFilter(new[] { typeof(MyFilter) })]
public ActionResult MyAction()
{
//some codes
}
So this way your filter of type MyFilter won't fire for specified action

How to develop action filter controller or action method specific

i was trying to develop a custom action filter which will check cookie is enable or not. if cookie is not enable then redirect use to a specific error page.here is my code.
public class CheckCookieAttribute : FilterAttribute, IActionFilter
{
public string prmAction{get;set;}
public string prmController{get;set;}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
if(filterContext.HttpContext.Request.Cookie["YourCookie"]==null)
{
filterContext.Result = controller.RedirectToAction(prmAction,prmController)
}
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
//The action filter logic - after
}
}
now i am using like
[CheckCookie(prmAction="MyAction",prmController="MyController")]
due to lack of good knowledge i am not being able to develop attribute driven check for cookie enable or disable.
i want to develop a code in such a way as a result i should not pass any controller name or action name. i like to use code like
[HttpPost]
[CheckCookieAttribute]
public ActionResult Save(Person oPerson)
{
return View();
}
[CheckCookieAttribute]
public class HomeController : Controller
{
public ActionResult Index()
{return View();}
public ActionResult About()
{return View();}
}
}
where i will not provide any name of controller or action name. just guide me what i need to change in my code. thanks
It seems that what you are trying to accomplish is already built into ASP.NET MVC.
I would use the [Authorize] attribute (http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute(v=vs.108).aspx) where you want to check if the user has a cookie.
If you want to redirect the user to a specific controller/action when the user is not authorized, you can use the following attribute instead:
public class AuthorizeUserAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(
new
{
controller = "Error",
action = "Unauthorized"
})
);
}
}
See ASP.NET MVC 4 Custom Authorize Attribute with Permission Codes (without roles)
Then you would use it by using:
[HttpPost]
[AuthorizeUser]
public ActionResult Save(Person oPerson)
{
return View();
}
Or if you want exactly what you asked for you can do it this way:
public class CheckCookieAttribute : ActionFilterAttribute, IActionFilter
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Request.Cookies["YourCookie"] == null)
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary { {"controller", "MyController"}, {"action", "MyAction"}});
}
else
{
base.OnActionExecuting(filterContext);
}
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
//The action filter logic - after
}
}

session becoming null in MVC AuthorizeAttribute

I am using an AuthorizeAttribute to check that users have an over 18 age cookie set to access pages.
This works fine, but I am extending in slightly now.
As all Views use this Attribute, I am using it to allow me to launch my site early.
If uses add ?VIEWSITE=true to any URL, it will set a Session variable, and allow them access to the site. Otherwise, they get directed to a holding page.
This works fine first time the page runs. But, I am using output caching on the page, and the next time the page loads, my httpcontext.session is null?
I've added an "Order" varible to my attributes to ensure they execute in the correct order:
[OfAge(Order = 1)]
[OutputCache(Order = 2, Duration = 2000, VaryByParam = "categoryName")]
Snipit from my Attribute:
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
HttpRequestBase req = httpContext.Request;
HttpResponseBase res = httpContext.Response;
DateTime Live_Date = new DateTime(2011, 07, 01, 07, 0, 0);
if (DateTime.Now > Live_Date || req.QueryString["VIEWSITE"] != null || httpContext.Session["VIEWSITE"] != null)
{
httpContext.Session["VIEWSITE"] = true;
Is there something I am missing here for me to be able to read/set session variables once a page is loaded from cache?
To be clear, it's httpContext.Session that is null, and not specifically httpContext.Session["VIEWSITE"]
3 years down the line and I ran into a similar issue. Now I'm no expert but I believe each controller context call is unique in it's own space, thus httpContext.Session would be null on a new call.
My issue came in the form of a logged in AD user I wanted to store (with his custom application permissions) in a session variable. I'm extending on the AuthorizationAttribute too, but when this filter is applied to a controller action, httpContext is null even though the user was saved.
For people battling with the same issue, the way around this is to create a base controller where this user and it's session state is kept throughout other controllers (inheriting the base controller).
ex.
My Model:
public class LoggedInUser
{
public somenamespace.userclass UserProfile { get; set; }
public List<somenamespace.user_permission_class> UserPermissions { get; set; }
}
My Base Controller:
public class ControllerBase : Controller
{
private LoggedInUser _LoginUser;
public LoggedInUser LoginUser
{
get
{
if (_LoginUser != null)
return _LoginUser;
if (Session["_LoginUser"] == null)
return null;
return Session["_LoginUser"] as LoggedInUser;
}
set
{
_LoginUser = value;
Session["_LoginUser"] = _LoginUser;
}
}
public void PerformUserSetup(string sUsername) // sUsername for testing another user, otherwise User.Identity will be used.
{
sUsername = string.IsNullOrEmpty(sUsername) ? User.Identity.Name : sUsername;
sUsername = (sUsername.IndexOf("\\") > 0) ? sUsername.Split('\\').ToArray()[1] : sUsername;
// Todo - SQL conversion to stored procedure
List<userclass> tmpUser = Root.Query<userclass>(/*sql to select user*/).ToList();
List<user_permission_class> tmpUserpermissions = Root.Query<user_permission_class>(/*sql to select user permissions*/).ToList();
LoggedInUser _LoginUser = new LoggedInUser();
_LoginUser.UserProfile = tmpUser.First();
_LoginUser.UserPermissions = tmpUserpermissions;
LoginUser = _LoginUser;
}
}
My HomeController (standard with any MVC example) :
public class HomeController : ControllerBase
{
[Authorize] // Standard AuthorizeAttribute (AD test)
public ActionResult Index()
{
if (Session["_LoginUser"] == null)
PerformUserSetup("");
return View();
}
}
My Custom permission checking filter which I'll use on any other controller action:
public class PermissionAuthorize : AuthorizeAttribute
{
private readonly string[] permissions;
public PermissionAuthorize(params string[] perms)
{
this.permissions = perms;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
bool auth = false;
if (httpContext.Session["_LoginUser"] == null)
{
// Do nothing as auth is false.
}
else
{
// Check permissions and set auth = true if permission is valid.
auth = true;
}
return auth;
}
/* not using
public override void OnAuthorization(AuthorizationContext filterContext)
{
var tmp = filterContext.HttpContext.Session;
}
*/
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
// Todo - direct to "unauth page"
base.HandleUnauthorizedRequest(filterContext);
}
}
Usage:
public class Some_OtherController : /*PossibleNamespace?.*/ControllerBase
{
[PermissionAuthorize("somepermission")] // This was a CRUD application thus 1 permission per actionresult
public ActionResult ViewWhatever()
{
....
}
}

Resources