using #User.IsInRole("Admin") in MVC VIEW - asp.net-mvc

I using #User.IsInRole("Admin") in mvc4
when i use this command in global.asax it return true but when I use in view of mvc it return sql server connection error .

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if (Context.User == null)
return;
var userService = ObjectFactory.GetInstance<IUserService>();
UserStatus userStatus = userService.GetStatus(Context.User.Identity.Name);
if (userStatus.IsBaned)
FormsAuthentication.SignOut();
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie == null || authCookie.Value == "")
return;
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
// retrieve roles from UserData
if (authTicket == null) return;
string[] roles = authTicket.UserData.Split(',');
if (userStatus.Role != roles[0])
FormsAuthentication.SignOut();
Context.User = new GenericPrincipal(Context.User.Identity, roles);
}

Related

Authorize Attribute with Roles

I want to implement my custom authorization, I wonder what is wrong with my code even I got the user credentials correctly it still redirects me to my Login Method, please see the code below
Edit: I have successfully implemented the Authorize Attribute with Roles, for future readers please see code below
Login Controller
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login (AdminViewModels.Login viewModel, string returnURL)
{
if (!ModelState.IsValid)
{
return View(viewModel);
}
PasswordHasher passwordVerify = new PasswordHasher();
var query = (from acc in db.accounts.Where(x => x.username == viewModel.Username)
select new { acc.username, acc.password}).FirstOrDefault();
if (query != null)
{
if (ModelState.IsValid)
{
var result = passwordVerify.VerifyHashedPassword(query.password, viewModel.Password);
switch (result)
{
case PasswordVerificationResult.Success:
//set forms ticket to be use in global.asax
SetupFormsAuthTicket(viewModel.Username, viewModel.rememeberMe);
return RedirectToLocal(returnURL);
case PasswordVerificationResult.Failed:
ModelState.AddModelError("", "Wrong Username or Password");
return View(viewModel);
}
}
}
return View(viewModel);
}
Forms Auth Ticket
private account SetupFormsAuthTicket(string userName, bool persistanceFlag)
{
account user = new account();
var userId = user.id;
var userData = userId.ToString(CultureInfo.InvariantCulture);
var authTicket = new FormsAuthenticationTicket(1, //version
userName, // user name
DateTime.Now, //creation
DateTime.Now.AddMinutes(20), //Expiration
persistanceFlag, //Persistent
userData);
var encTicket = FormsAuthentication.Encrypt(authTicket);
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
return user;
}
Global.asax
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
if (FormsAuthentication.CookiesSupported == true)
{
if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
try
{
//take out user name from cookies
string username = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;
string[] roles = null;
trainingEntities db = new trainingEntities();
//query database to get user roles
var query = (from acc in db.account_roles where acc.account.username == username select acc.role.role_name).ToArray();
roles = query;
//Let us set the Pricipal with our user specific details
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(
new System.Security.Principal.GenericIdentity(username, "Forms"), roles);
}
catch (Exception)
{
//somehting went wrong
}
}
}
}
Now you can use [Authorize(Roles = "Admin")]
to any action method or on top of controller
I have successfully implemented the Authorize Attribute with Roles, for future readers please see code below.
Login Controller
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login (AdminViewModels.Login viewModel, string returnURL)
{
if (!ModelState.IsValid)
{
return View(viewModel);
}
PasswordHasher passwordVerify = new PasswordHasher();
var query = (from acc in db.accounts.Where(x => x.username == viewModel.Username)
select new { acc.username, acc.password}).FirstOrDefault();
if (query != null)
{
if (ModelState.IsValid)
{
var result = passwordVerify.VerifyHashedPassword(query.password, viewModel.Password);
switch (result)
{
case PasswordVerificationResult.Success:
//set forms ticket to be use in global.asax
SetupFormsAuthTicket(viewModel.Username, viewModel.rememeberMe);
return RedirectToLocal(returnURL);
case PasswordVerificationResult.Failed:
ModelState.AddModelError("", "Wrong Username or Password");
return View(viewModel);
}
}
}
return View(viewModel);
}
FormsAuthTicket
private account SetupFormsAuthTicket(string userName, bool persistanceFlag)
{
account user = new account();
var userId = user.id;
var userData = userId.ToString(CultureInfo.InvariantCulture);
var authTicket = new FormsAuthenticationTicket(1, //version
userName, // user name
DateTime.Now, //creation
DateTime.Now.AddMinutes(20), //Expiration
persistanceFlag, //Persistent
userData);
var encTicket = FormsAuthentication.Encrypt(authTicket);
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
return user;
}
Global.asax
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
if (FormsAuthentication.CookiesSupported == true)
{
if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
try
{
//take out user name from cookies
string username = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;
string[] roles = null;
trainingEntities db = new trainingEntities();
//query database to get user roles
var query = (from acc in db.account_roles where acc.account.username == username select acc.role.role_name).ToArray();
roles = query;
//Let us set the Pricipal with our user specific details
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(
new System.Security.Principal.GenericIdentity(username, "Forms"), roles);
}
catch (Exception)
{
//somehting went wrong
}
}
}
}
Now you can use [Authorize(Roles = "Admin")]
to any action method or on top of controller
as I see in ControllerLogin attribute it is now being applied in a variable, when it should be applied to a method or a class
[CustomAuthorization(UserRole="Admin")]
// GET: Manage
private trainingEntities db = new trainingEntities();
public ActionResult Index()
{
return View();
}
Private trainingEntities dB = new TrainingEntities();
[CustomAuthorization(UserRole="Admin")]
Public ActionResult Index()
{
//yourcode
}

Authorize attribute doesn't work in MVC

I have a User with a role of Member. I have this Login Action:
public virtual ActionResult Login(string returnUrl)
{
if(User.Identity.IsAuthenticated)
{
if (IsValidReturnUrl(returnUrl))
return Redirect(returnUrl);
return Redirect(FormsAuthentication.DefaultUrl);
}
return View();
}
And I have this ActionMethod :
[Authorize(Roles="Member")]
public virtual ActionResult PostLostThing()
{
var maingroups = _maingroups.SelectAll();
var Provinces = _provinces.SelectAll();
ViewBag.MainGroups = new SelectList(maingroups, "GroupId", "GroupName", maingroups.FirstOrDefault().GroupId);
ViewBag.SubGroups = new SelectList(maingroups.FirstOrDefault().SubGroups, "id", "name");
ViewBag.Provinces = new SelectList(Provinces, "Id", "Title", Provinces.FirstOrDefault().Id);
ViewBag.Cities = new SelectList(Provinces.FirstOrDefault().Cities, "Id", "Name");
return View();
}
When user is logged in and call view PostLostThing it redirects to Login Page, but when the Role of Authorize attribute is removed, it works very well. I have this SetAuthCookie method:
private void SetAuthCookie(string memberName, string roleofMember, bool presistantCookie)
{
var timeout = presistantCookie ? FormsAuthentication.Timeout.TotalMinutes : 30;
var now = DateTime.UtcNow.ToLocalTime();
var expirationTimeSapne = TimeSpan.FromMinutes(timeout);
var authTicket = new FormsAuthenticationTicket(
1,
memberName,
now,
now.Add(expirationTimeSapne),
presistantCookie,
roleofMember,
FormsAuthentication.FormsCookiePath
);
var encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
{
HttpOnly = true,
Secure = FormsAuthentication.RequireSSL,
Path = FormsAuthentication.FormsCookiePath
};
if (FormsAuthentication.CookieDomain != null)
{
authCookie.Domain = FormsAuthentication.CookieDomain;
}
if (presistantCookie)
authCookie.Expires = DateTime.Now.AddMinutes(timeout);
Response.Cookies.Add(authCookie);
}
What's the problem?
Since you're setting the auth cookie yourself, you need to implement the Application_AuthenticateRequest in the Global.asax.cs file. Otherwise, nothing beyond the user name is added to the Principal object.
Here's a sample implementation:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
string[] roles = null;
GenericPrincipal userPrincipal = new GenericPrincipal(new GenericIdentity(authTicket.Name), roles);
Context.User = userPrincipal;
}
}
The overload you're using assumes that the value you've passed roleofMember is actually some serialized data. You then need to tell it how to handle deserializing that user data. Since you're just passing a single role name, you can amend the sample above to:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
string[] roles = new string [] { authTicket.UserData };
GenericPrincipal userPrincipal = new GenericPrincipal(new GenericIdentity(authTicket.Name), roles);
Context.User = userPrincipal;
}
}

why HttpContext.Current.User Could not be initialized is reurn null

I'm using this code for Authentication mvc .I am login but Context.User is null when trace project show current.user null.
I think Context.User Could not be initialized
how sloved this problem
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if (Context.User == null)
return;
var userService = ObjectFactory.GetInstance<IUserService>();
var userStatus = userService.GetStatus(Context.User.Identity.Name);
if (userStatus.IsBaned)
FormsAuthentication.SignOut();
var authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie == null || authCookie.Value == "")
return;
var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
// retrieve roles from UserData
if (authTicket == null) return;
var roles = authTicket.UserData.Split(',');
if (userStatus.Role != roles[0])
FormsAuthentication.SignOut();
Context.User = new GenericPrincipal(Context.User.Identity, roles);
}
private void SetAuthCookie(string userName, string roleofUser, bool presistantCookie)
{
var timeout = presistantCookie ? FormsAuthentication.Timeout.TotalMinutes : 30;
var now = DateTime.UtcNow.ToLocalTime();
var expirationTimeSapne = TimeSpan.FromMinutes(timeout);
var authTicket = new FormsAuthenticationTicket(
1,
userName,
now,
now.Add(expirationTimeSapne),
presistantCookie,
roleofUser,
FormsAuthentication.FormsCookiePath
);
var encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
{
HttpOnly = true,
Secure = FormsAuthentication.RequireSSL,
Path = FormsAuthentication.FormsCookiePath
};
if (FormsAuthentication.CookieDomain != null)
{
authCookie.Domain = FormsAuthentication.CookieDomain;
}
if (presistantCookie)
authCookie.Expires = DateTime.Now.AddMinutes(timeout);
Response.Cookies.Add(authCookie);
}

MVC 3 Redirect not working

I have a small problem related to action redirecting. I want to prevent users from being able to access information concerning a specific area in the site using an override of the OnActionExecuting in my BaseController class, which is the base class for all my controllers. Method body:
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (Request.IsAuthenticated && (User as Eagle.Security.EaglePrincipal != null) && Session != null && Session["LastKnownGoodArea"] != null && filterContext.ActionDescriptor.ActionName != "InvalidPermission")
{
var currentArea = Principal.CurrentCenter.CODEFORM_CSE;
if (currentArea != Session["LastKnownGoodArea"].ToString())
RedirectToActionPermanent("InvalidPermission", "Account", new { target = 0, redirectURL = null as string });
else
base.OnActionExecuting(filterContext);
}
}
However, this does not redirect to the specified action. What am I doing wrong? What other approach, if any, would you guys suggest?
Thanks,
Silviu
What Dave commented is right ! In addition this should be the syntax you are looking for :-
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (Request.IsAuthenticated && (User as Eagle.Security.EaglePrincipal != null) && Session != null && Session["LastKnownGoodArea"] != null && filterContext.ActionDescriptor.ActionName != "InvalidPermission")
{
var currentArea = Principal.CurrentCenter.CODEFORM_CSE;
if (currentArea != Session["LastKnownGoodArea"].ToString())
{
filterContext.Result = new RedirectToRouteResult(new
RouteValueDictionary(new
{
controller = "InvalidPermission",
action = "Account",
target = 0,
}));
filterContext.Result.ExecuteResult(filterContext);
}
else
{
base.OnActionExecuting(filterContext);
}
}
}
I want to prevent users from being able to access information concerning a specific area in the site using an override of the OnActionExecuting in my BaseController class, which is the base class for all my controllers.
Why did you choose to use OnActionExecuting for this? You're executing this if-statement on every request, I would recommend to use the Authorize attribute for the specific actions:
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var user = User as Eagle.Security.EaglePrincipal;
if(httpContext.User.Identity.IsAuthenticated && user != null)
{
var currentArea = Principal.CurrentCenter.CODEFORM_CSE;
var lastKnownArea = Session["LastKnownGoodArea"];
if (lastKnowArea == null)
return false;
return currentArea.Equals(lastKnownArea.ToString());
}
return base.AuthorizeCore(httpContext);
}
}
In your web.config you can configure redirects like:
<customErrors mode="RemoteOnly">
<error statusCode="403" redirect="/InvalidPermission/Account" />
</customErrors>
If you want control over the UnAuthorized request you can always choose to override the HandleUnauthorizedRequest method
Here is the final solution:
var currentArea = Principal.CurrentCenter.CODEFORM_CSE;
if (currentArea != Session["LastKnownGoodArea"].ToString())
{
filterContext.Result = new RedirectToRouteResult(new
RouteValueDictionary(new
{
controller = "Account",
action = "InvalidPermission",
area = "",
target = 0,
redirectURL = ""
}));
}
else
{
base.OnActionExecuting(filterContext);
}
Thank you both for your input, you helped alot!
Cheers!
You can't redirect to Action from a filter because it is not creating an Action Result yet. You can only create a new route. I'm not completely sure of syntax you need. I threw this together as an example of way to go.
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (Request.IsAuthenticated && (User as Eagle.Security.EaglePrincipal != null) && Session != null && Session["LastKnownGoodArea"] != null && filterContext.ActionDescriptor.ActionName != "InvalidPermission")
{
var currentArea = Principal.CurrentCenter.CODEFORM_CSE;
if (currentArea != Session["LastKnownGoodArea"].ToString())
filterContext.Result = new RedirectToRouteResult(
new System.Web.Routing.RouteValueDictionary {
{"controller", "InvalidPermission"}, {"action", "Account"}, {target =0}, {redirectURL = null as string }
else
base.OnActionExecuting(filterContext);
}
}

mvc 4 can not be custom Authorize roles

HomeController
[Authorize(Roles = "Member")]
public ActionResult Contact()
{
return View();
}
Global.asax
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
//Construst the GeneralPrincipal and FormsIdentity objects
var authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (null == authCookie)
{
//no authentication cokie present
return;
}
var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
if (null == authTicket)
{
//could not decrypt cookie
return;
}
//get the role
var role = authTicket.UserData.Split(new[] { ',' });
var id = new FormsIdentity(authTicket);
Context.User = new GenericPrincipal(id, role);
}
AccountController
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid && _userbll.ValidateUser(model.UserName, model.Password))
{
var ticket = new FormsAuthenticationTicket(1, model.UserName, DateTime.Now, model.RememberMe ? DateTime.Now.AddDays(14) : DateTime.Now.AddMinutes(30), model.RememberMe, "Member");
var hashTicket = FormsAuthentication.Encrypt(ticket);
var userCookie = new HttpCookie(FormsAuthentication.FormsCookieName, hashTicket);
Response.Cookies.Add(userCookie);
return RedirectToLocal(returnUrl);
}
ModelState.AddModelError("", "error");
return View(model);
}
FormsAuthenticationTicket userData= "Member"
at last,use the mechanism of Membership Role made in built
结果还是使用了 Membership Role 内置的机制
mvc3 can be read userData

Resources