Reputation: 2313
I'm creating ASP.NET MVC 4 Internet Application.
In that Application I created Login Page that any user can log in to, then I allowed to redirect user to different pages based on their role.
ASP.NET Identity is the membership system here.
This is my Login Controller method:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindAsync(model.UserName, model.Password);
if (user != null)
{
if (user.ConfirmedEmail == true)
{
await SignInAsync(user, model.RememberMe);
if (String.IsNullOrEmpty(returnUrl))
{
if (UserManager.IsInRole(user.Id, "HEC_Admin"))
{
return RedirectToAction("Index", "HEC");
}
//role Admin go to Admin page
if (UserManager.IsInRole(user.Id, "HEI_User"))
{
return RedirectToAction("Index", "HEI");
}
}
else
{
return RedirectToLocal(returnUrl);
}
}
else
{
ModelState.AddModelError("", "Confirm Email Address.");
}
}
else
{
ModelState.AddModelError("", "Invalid username or password.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
This is HEI Controller Class:
public class HEIController : Controller
{
//
// GET: /HEI/
[Authorize(Roles = "HEI_User")]
public ActionResult Index()
{
return View();
}
}
This is my HEC Controller Class:
public class HECController : Controller
{
//
// GET: /HEC/
[Authorize(Roles = "HEC_Admin")]
public ActionResult Index()
{
return View();
}
}
when I remove [Authorize(Roles = "HEC_Admin")] above the index action in HECController class and when I remove [Authorize(Roles = "HEC_User")] above the index action in HEIController class this is working fine,
but then How restrict unauthorized access to these pages?
Upvotes: 2
Views: 4786
Reputation: 36
I had the same problem as you and I still don't know the reason why it happens. What I did was to create my own custom Authorization Attribute and check the Roles myself.
public class CustomAuthorizationAttribute : AuthorizeAttribute
{
public string IdentityRoles
{
get { return _identityRoles ?? String.Empty; }
set
{
_identityRoles = value;
_identityRolesSplit = SplitString(value);
}
}
private string _identityRoles;
private string[] _identityRolesSplit = new string[0];
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//do the base class AuthorizeCore first
var isAuthorized = base.AuthorizeCore(httpContext);
if (!isAuthorized)
{
return false;
}
if (_identityRolesSplit.Length > 0)
{
//get the UserManager
using(var um = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
{
var id = HttpContext.Current.User.Identity.GetUserId();
//get the Roles for this user
var roles = um.GetRoles(id);
//if the at least one of the Roles of the User is in the IdentityRoles list return true
if (_identityRolesSplit.Any(roles.Contains))
{
return true;
}
}
return false;
}
else
{
return true;
}
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
//if the user is not logged in use the deafult HandleUnauthorizedRequest and redirect to the login page
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
base.HandleUnauthorizedRequest(filterContext);
}
else
//if the user is logged in but is trying to access a page he/she doesn't have the right for show the access denied page
{
filterContext.Result = new RedirectResult("/AccessDenied");
}
}
protected static string[] SplitString(string original)
{
if (String.IsNullOrEmpty(original))
{
return new string[0];
}
var split = from piece in original.Split(',')
let trimmed = piece.Trim()
where !String.IsNullOrEmpty(trimmed)
select trimmed;
return split.ToArray();
}
}
I also added the HandleUnauthorizedRequest
method to redirect to a appropriated page if the user has is logged in but has no access to this action or controller
To use it just do this:
[CustomAuthorization(IdentityRoles = "HEI_User")]
public ActionResult Index()
{
return View();
}
Hope it helps.
Upvotes: 2