Authorize attribute in MVC order, priority and function question
There is something in the roles I don't exactly get. using the [Authorize]
attribute
When you have the [Authorize]
attribute on the controller and on the action:
- Whe开发者_如何学JAVAn a role is in both, this role will have access
- When a role is only defined at the Controller, but not at the Action, no access
- When a role is only defined at the Action, but not at the Controller, no access
I get that, that's logical. You need access to the controller before you can run an action.
What I dont get is why this doesnt work:
[Authorize(Roles = "Algemeen Beheer, Admin, Coordinator, Secretariaat")]
public class FacturatieGegevensController : Controller {
[Authorize(Users = "Stefan.coordinator", Roles = "Algemeen Beheer, Admin")]
public ActionResult Create(int instID) {
return View();
}
}
When I am logged in as user Stefan.coordinator
which has the role coordinator
, I can access the controller, but I can not access the Create Action.
I thought this would be an OR relation between Users
and Roles
. Is it not? and how do I get this to work?
The condition to access the Create method is:
((ROLE in { Algemeen Beheer, Admin, Coordinator, Secretariaat })) [from controller-level] AND ((USER in { Stefan.coordinator }) AND (ROLE in { Algemeen Beheer, Admin })) [from method-level]
Once all the ANDs / ORs have been worked out, this results in simply:
USER in { Stefan.coordinator } AND ROLE in { Algemeen Beheer, Admin }
That is, within a particular AuthorizeAttribute, the Users and Roles are ANDed together. And across multiple AuthorizeAttributes, the conditions are ANDed together.
The best way to think of this is that the [Authorize] attributes are not aware of each other, so each executes independently. The controller-level one goes first, then the method-level one goes. To get access to the method, you need to pass all gates.
Edit - there was a question on how the logic works out as it does above.
Let:
A = ROLE is "Algemeen Beheer"
B = ROLE is "Admin"
C = ROLE is "Coordinator"
D = ROLE is "Secretariaat"
E = USER is "Stefan.coordinator"
Since the controller-level [Authorize] attribute is (A || B || C || D), the method-level [Authorize] attribute is (E && (A || B)), and multiple [Authorize] attributes are represented by a logical AND, the logic ends up as (A || B || C || D) && (E && (A || B)), which reduces to E && (A || B), which requires the user to be named "Stefan.coordinator" and to be in the "Algemeen Beheer" or "Admin" roles. Since the user Stefan.coordinator isn't in either of these two roles, the check fails.
To your particular problem..
If you want to apply your own logic to the [Authorize] attribute checks, subclass AuthorizeAttribute and override the AuthorizeCore method. That way you can say if (User == "Stefan.coordinator" || base.AuthorizeCore(...)) { ... }.
The [Authorize]
specified at controller level is the default, used when there is no [Authorize]
specified for an individual action method.
The two do not work together, and only one will ever get executed.
If you specify both a user and roles in the [Authorize]
filter, then both must be satisfied to allow access to the method.
Therefore it's an AND not OR.
精彩评论