ASP.NET MVC 3 Controller Extension Method - asp.net-mvc

I am new to mvc 3 and I'm using it with the asp.net membership provider....so I'd like to create an extension method to let me get the logged user GUID from any controller whitin my website
Something like that:
public static Guid GetLoggedUser(this Controller controller)
{
return (Guid)Membership.GetUser(controller.User.Identity.Name).ProviderUserKey.ToString();
}
Any ideas?

Why not use "User" property already on the ControllerBase class?
public class MyController : Controller
{
public ActionResult GetUser()
{
var userName = User.Identity.Name;
}
}
You can include additional information about your user by using a custom IPrincipal/IIdentity. Here's how it is done if using Forms Auth.

Related

AuthorizeAttribute. Grant access to some action in controller for different role

There are two roles in my application: Admin and ContentMaker. Admin has full access and ContentMaker can create\edit articles. One user has one role (one-to-one).
Although i have only one AdminController for all stuff (include manage articles) decorated with AuthorizeAttribute. I want to grant access only to edit articles for ContentMaker within AdminController. The problem is contentmaker IS NOT admin so he has no access to AdminController in all. Is it possible to extend AuthorizeAttribute to let this behavior? This is what i want:
//only Admin can access this controller
[Authorize(Roles = ConstantsWeb.Database.AdminRoleName)]
public partial class AdminController : Controller
{
//ContentMaker has no access here
public ActionResult SomeAdminStuffAction()
{
//code
}
//ContentMaker only has access here, although he is not Admin
[Authorize(Roles = ConstantsWeb.Database.ContentMakerRoleName)]
public ActionResult EditArticle(int id)
{
//code
}
}
It is easy solution. Since ASP.NET MVC 5 here is OverrideAuthorization attribute. It let to override access permissions for any actions in controller. You need to put OverrideAuthorization attribute and another Authorize attribute. Like this:
//only Admin can access this controller
[Authorize(Roles = ConstantsWeb.Database.AdminRoleName)]
public partial class AdminController : Controller
{
//ContentMaker has no access here
public ActionResult SomeAdminStuffAction()
{
//code
}
//ContentMaker only has access here, although he is not Admin
[OverrideAuthorization]
[Authorize(Roles = ConstantsWeb.Database.AdminRoleName + "," + ConstantsWeb.Database.ContentMakerRoleName)]
public ActionResult EditArticle(int id)
{
//code
}
}

How do I add permission to a view or controller dynamically?

In all of my asp.net mvc projects up to this point, permissions to controllers are set by using a custom class based on the [Authorize] attribute.
However, what if I wanted an administrator role who could grant access to views instead of going through the trouble of having to touch the controller to add/remove roles, re-complile, and push the changes to production. How would I go about doing this?
as discussed. Try the below.
in the controller as I'm sure you're aware.
[PermissionsFilter("CanAccessMyView")]
public ActionResult ReturnMyView ()
{
//etc..
}
Then, in your custom class
public class PermissionsFilter : AuthorizeAttribute
{
private readonly PermissionManager _permissionsManager;
public PermissionsFilter(string permissionName)
{
_permissionName = permissionName;
_permissionsManager = new PermissionServiceManager();
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (!_permissionServiceManager.CanAccessPermission(_permissionName))
{
var urlHelper = new UrlHelper(filterContext.RequestContext);
var url = urlHelper.Action("Unauthorised", "Home");
filterContext.Result = new RedirectResult(url);
}
}
}
Where the permissions manager is querying the database or perhaps session info to see if the user user has access.
Hope that helps.

How to restrict access to certain actions in controller in ASP.net MVC

I am new to ASP.net MVC and created my first web application using it. In my application I am using database authentication. I have created Login action in controller which checks entered username and password exist in DB or not, If it exist then put required values in Session and redirect user to pages as per his rights else redirect user to login page. Like this
public ActionResult Login()
{
if(uservalid)
{
//set session values and redirect to dashboard
}
else
{
//redirect to login
}
}
In my application there are some functionality that can only be accessed when user is logged-in. I want to check whether user is logged-in or not before user try to access these functionality and if he is not logged-in or not have rights then redirect to login page or show some error message.
public ActionResult SomeAction()
{
//Available only when user is logged-in
}
So how do I check whether user is logged-in or not and give access to action. I read about Authorize attribute but don't know how to use it as I am using database authentication.
If you are using FormsAuthentication you don't need to use ASP.NET session to track the currently authenticated user.
I read about Authorize attribute but don't know how to use it as I am
using database authentication.
Assuming you went with FormsAuthentication, once you have validated the credentials of the user you should set a forms authentication cookie:
public ActionResult Login()
{
if(uservalid)
{
FormsAuthentication.SetAuthCookie("username", false);
return RedirectToAction("SomeProtectedAction");
}
else
{
//redirect to login
}
}
and then:
[Authorize]
public ActionResult SomeAction()
{
string currentlyLoggedInUser = User.Identity.Name;
}
By the way if you create a new ASP.NET MVC application using the internet template in Visual Studio you might take a look at the AccountController which is responsible for authenticating users and setting forms authentication cookies. Of course you could throw all the Entity Framework crap out of it and implement your own credentials validation against your own database tables.
I apply [Authorize] as well as my own customattribute for restricting the action based on permission. The code is below
[Authorize]
[FeatureAuthentication(AllowFeature=FeatureConst.ShowDashboard)]
public ActionResult Index()
{
}
Filter code
public class FeatureAuthenticationAttribute : FilterAttribute, IAuthorizationFilter
{
public FeatureConst AllowFeature { get; set; }
public void OnAuthorization(AuthorizationContext filterContext)
{
//var featureConst = (FeatureConst)filterContext.RouteData.Values["AllowFeature"];
var filterAttribute = filterContext.ActionDescriptor.GetFilterAttributes(true)
.Where(a => a.GetType() == typeof(FeatureAuthenticationAttribute));
if (filterAttribute != null)
{
foreach (FeatureAuthenticationAttribute attr in filterAttribute)
{
AllowFeature = attr.AllowFeature;
}
User currentLoggedInUser = (User)filterContext.HttpContext.Session["CurrentUser"];
bool allowed = ACLAccessHelper.IsAccessible(AllowFeature.ToString(), currentLoggedInUser);
// do your logic...
if (!allowed)
{
string unAuthorizedUrl = new UrlHelper(filterContext.RequestContext).RouteUrl(new { controller = "home", action = "UnAuthorized" });
filterContext.HttpContext.Response.Redirect(unAuthorizedUrl);
}
}
}
}
you should create a basecontroller and inherit other controlers from base controller and then check whether the session is null or not to authenticate users.
public class BaseController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (Session["User"]== null)
{
filterContext.HttpContext.Response.Redirect("/somepage");
}
}
public class SomeController : BaseController
{
}
There are multiple ways of doing it but the preferred way would be to use the Annotation. Here is a post for it
How to get custom annotation attributes for a controller action in ASP.NET MVC 4?
If you are getting started I would suggest to follow the tutorial on
http://www.asp.net/mvc

create the authorize filter with parameter asp.net mvc

I have to develop an authorize filter in asp.net mvc.I have got five categories of users in my site and my site uses custom created authentication system.Now i have a controller action which should be accessible to 3 out of those five type of users.How to create a filter (basically authorize) and use it which fulfills my requirement?I think i need to create the authorize filter with parameter.I should be able to use something like this.
Authorize[UsersType="admin,accountant,operator"]
technology used : Asp.net MVC
Thanks in Advance
Create an Attribute class that Inherits the AuthorizeAttribute class of MVC.
Create a constructor in your attribute class that accepts the parameter UsersType
Override the appropriate methods of AuthorizeAttribute that is needed.
Parse the parameter in your appropriate override method.
public class AuthorizeUserAttribute :AuthorizeAttribute
{
private string[] _userType { get; set; }
public AuthorizeUserAttribute(string UsersType)
{
// parse your usertypes here.
}
protected override void OnAuthorization(AuthorizationContext filterContext)
{
// do the appropriate assigning and authorizing of methods here
....
base.OnAuthorization(filterContext);
}
}
Now you can put an attribute in your Method in your controller
[AuthorizeUser("admin,accountant,operator")]
public ActionMethod Index()
{
return View();
}

Overriding controller AuthorizeAttribute for just one action

I have a controller decorated with an AuthorizeAttribute. The controller contains several actions that all require authentication apart from one action that requires some custom authentication provided by CustomAuthorizeAttribute.
My question is once I've added [Authorize] at the controller level can I override it (or remove it) with [CustomAuthorize] on just one action? Or do I have to remove [Authorize] from the controller level and add it individually to every other action?
I'm asking purely for convenience because I'm lazy and don't want to decorate every action with the AuthorizeAttribute.
[Authorize]
public class MyController : Controller {
//requires authentication
public ViewResult Admin() {
return View();
}
//... a lot more actions requiring authentication
//requires custom authentication
[CustomAuthorize] //never invoked as already failed at controller level
public ViewResult Home() {
return View();
}
}
In MVC 5 you can override the authorization for any action using the new attribute OverrideAuthorization. Basically, you add it to an action that has a different authorization configuration than the one defined in the controller.
You do it like this:
[OverrideAuthorization]
[Authorize(Roles = "Employee")]
public ActionResult List() { ... }
More information at http://www.c-sharpcorner.com/UploadFile/ff2f08/filter-overrides-in-Asp-Net-mvc-5/
In ASP.NET Core 2.1 there's no OverrideAuthorization attribute and the only thing you can do is make an action anonymous, even if the controller is not. More information at https://learn.microsoft.com/en-us/aspnet/core/security/authorization/roles?view=aspnetcore-2.1
One option is to do it this way:
[Authorize(Roles = "Admin,Employee")] // admin or employee
public class XController : Controller
{
[Authorize(Roles = "Admin")] // only admin
public ActionResult ActionX() { ... }
[AllowAnonymous] // anyone
public ActionResult ActionX() { ... }
}
You can change the Order in which the attributes run (using the Order property), but I believe that in this case they will still both run unless one generates a result with immediate effect. The key is to have the least restrictive attribute applied at the highest level (class) and get more restrictive for the methods. If you wanted the Home action to be publicly available, for instance, you would need to remove the Authorize attribute from the class, and apply it to each of the other methods.
If the action has the same level of permissiveness, but has a different result, changing the order may be sufficient. For example, you would normally redirect to the Logon action, but for Home you want to redirect to the About action. In this, case give the class attribute Order=2 and the Home action attribute Order=1.
After way too much time, I came up with a solution. You need to decorate your controller with a custom AuthorizeAttribute.
public class OverridableAuthorize : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
var action = filterContext.ActionDescriptor;
if(action.IsDefined(typeof(IgnoreAuthorization), true)) return;
var controller = action.ControllerDescriptor;
if(controller.IsDefined(typeof(IgnoreAuthorization), true)) return;
base.OnAuthorization(filterContext);
}
}
Which can be paired with AllowAnonymous on an Action
[AllowAnonymous]
All you need to override the [Authorize] from the controller, for a specific action is to add
[AllowAnonymous]
to the action you want to not be authorized (then add your custom attribute as required).
See the comments / intellisense :
Represents an attribute that marks controllers and actions to skip the
System.Web.Mvc.AuthorizeAttribute during authorization.
Full Example
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Diagnostics;
using System.Threading.Tasks;
namespace Website
{
public class CustomAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
if (true)//Perform own authorization logic
return; //simply return if request is authorized
context.Result = new UnauthorizedResult();
return; //this is not authorized
}
}
[Authorize]
public class WebsiteController : Controller
{
[HttpGet]
[AllowAnonymous]//When this is added our Custom Attribute is hit, without it our attribute is not used as request already gets 401 from controller's Authorize
[CustomAuthorize]
public IActionResult Index()
{
return View(new ViewModel());
}
}
Note
This approach will not work if you want to use the standard [Authorize] attribute on your action, with a custom policy e.g.
[Authorize]
public class WebsiteController : Controller
{
[HttpGet]
[AllowAnonymous]
[Authorize("CustomPolicyName")] //Will not be run
public IActionResult Index()
{
return View(new ViewModel());
}
}
services.AddAuthorization(options =>
{
options.AddPolicy("BadgeEntry", policy =>
policy.RequireAssertion(context =>
false //Custom logic here
));
});
...but if like the OP you want a Custom Attribute then you are good to go with my solution.
Override for all controllers when handling prototype and production environment.
So there is no need to remove the authorize of each controller.
app.UseEndpoints(endpoint =>
{
endpoint.MapControllers().WithMetadata(new AllowAnonymousAttribute());
});

Resources