问题
Project Overview: Working in dashboard Views on back-end of project. I have a Permission driven Menu. Menu gets populated when User logs in and views dashboard. Currently the User sees all the buttons IE: delete, edit, details, create. I would like to hide those buttons from the view. Currently they can select it and it will redirect to a UnAuthorized page if they do not have access.
I have a Menu / MenuPermissions tables that bits are set if the user has access or not. I am looking for something to utilize this information to hide the buttons.
I have created a ActionLink Extension with a couple of classes to turn a bit true or False, but it requires me to have
[Authorize(Roles = "Administration")]
in the controller action. This not desirable as i have the flexibility to edit, create, and delete Roles.
I have looked at several Tutorials and they all seem to relate to Asp.Net Core, which my project is not and do not need it to be.
I found what i needed in this post: asp-net-how-to-hide-or-show-a-link-button
However it is an incomplete Question - There is no answer to this question that was accepted. Apparently the person has figured it out but did not bother to show what he did..
This is the ActionLink extension example i have tried:
@Html.ActionLinkAuthorized("Edit Roles", "Edit", "Roles", new { UserName = item.UserName }, new { @class = "btn btn-warning btn-sm" }, true)
This, Like i said requires the controller to have it set as Authorized. The Code below is used as a OnActionExecuting(context) Which is past the point that i would need it. However could help in finding a usable solution.
string userid = Env.GetUserInfo("userid");
string roleid = Env.GetUserInfo("roleid");
var descriptor = context.ActionDescriptor;
var actionName = descriptor.ActionName.ToLower();
var controllerName = descriptor.ControllerDescriptor.ControllerName.ToLower();
var GetOrPost = context.HttpContext.Request.HttpMethod.ToString();
var checkAreaName = context.HttpContext.Request.RequestContext.RouteData.DataTokens["area"];
The Next two areas aid in finding if the user is authorized based on menu permissions:
private bool IsActionNameEqualToCrudPageName(string actionName)
{
bool ActionIsCrud = false;
switch (actionName)
{
case "add":
ActionIsCrud = true;
break;
case "create":
ActionIsCrud = true;
break;
case "index":
ActionIsCrud = true;
break;
case "details":
ActionIsCrud = true;
break;
case "edit":
ActionIsCrud = true;
break;
case "multiviewindex":
ActionIsCrud = true;
break;
case "delete":
ActionIsCrud = true;
break;
default:
ActionIsCrud = false;
break;
}
return ActionIsCrud;
}
private void CheckAccessOfPageAction(ActionExecutingContext context, string actionName, MenuOfRole checkRoleUrlCrud)
{
switch (actionName)
{
case "add":
if (checkRoleUrlCrud.IsAdd == false)//Check Crud
{
UnAuthoRedirect(context);
}
break;
case "create":
if (checkRoleUrlCrud.IsCreate == false)//Check Crud
{
UnAuthoRedirect(context);
}
break;
case "index":
if (checkRoleUrlCrud.IsRead == false)//Check Crud
{
UnAuthoRedirect(context);
}
break;
case "details":
if (checkRoleUrlCrud.IsRead == false)//Check Crud
{
UnAuthoRedirect(context);
}
break;
case "edit":
if (checkRoleUrlCrud.IsUpdate == false)//Check Crud
{
UnAuthoRedirect(context);
}
break;
case "multiviewindex":
if (checkRoleUrlCrud.IsUpdate == false)//Check Crud
{
UnAuthoRedirect(context);
}
break;
case "delete":
if (checkRoleUrlCrud.IsDelete == false)//Check Crud
{
UnAuthoRedirect(context);
}
break;
default:
break;
}
}
The code that is below is in the class that is used to hide the button - Again it requires that the Authorize is set in the Controller.
public static bool ActionAuthorized(this HtmlHelper htmlHelper, string actionName, string controllerName)
{
ControllerBase controllerBase = string.IsNullOrEmpty(controllerName) ? htmlHelper.ViewContext.Controller : htmlHelper.GetControllerByName(controllerName);
ControllerContext controllerContext = new ControllerContext(htmlHelper.ViewContext.RequestContext, controllerBase);
ControllerDescriptor controllerDescriptor = new ReflectedControllerDescriptor(controllerContext.Controller.GetType());
ActionDescriptor actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
if (actionDescriptor == null)
return false;
FilterInfo filters = new FilterInfo(FilterProviders.Providers.GetFilters(controllerContext, actionDescriptor));
AuthorizationContext authorizationContext = new AuthorizationContext(controllerContext, actionDescriptor);
foreach (IAuthorizationFilter authorizationFilter in filters.AuthorizationFilters)
{
authorizationFilter.OnAuthorization(authorizationContext);
if (authorizationContext.Result != null)
return false;
}
return true;
}
Then there are link extensions to use in another file.
If someone could point me in the right direction as to how i can use the code i already have to check menu permissions and then hide the button without hard-coding, It would be appreciated. Or if there is a simpler way of doing this that would also work.
The end result is to get rid of the redirect. My project does not like it because it tries to pass headers after headers are already set - Via "Log-Out".
Thanks for your help on this.
UPDATE:
This has been resolved in another post i posted. stackoverflow.com/questions/11668261
回答1:
I do this the same way as the highly upvoted in the question you linked to. https://stackoverflow.com/a/11668462/5367916
A very simplified version:
.cshtml
@if (User.IsInRole("Admin"))
{
<button>Admin power button</button>
}
The downside of this is that it means there is no automatic link between your implementation:
[Authorize(Roles = "Admin")]
and your check in the cshtml. I at least make it strongly typed by using enums and custom attributes and methods for my securables in my role-based security implementation.
@if (User.HasSecurable(Securable.AdminPower))
{
<button>Admin power button</button>
}
[AllowSecurables(Securable.AdminPower)]
public ActionResult AdminPower()
{
}
来源:https://stackoverflow.com/questions/60141639/hide-button-on-view-based-on-auth-access-in-aspnet-mvc-without-hard-coding-aut