kas*_*ter 16 asp.net-mvc authorization
当我有用户登录时,我正在阅读有关登录循环的另一个问题,设置为返回登录后可能无法访问的URL(即管理员页面,用户使用普通帐户登录) .
WebForms下的解决方案似乎是利用该UrlAuthorizationModule.CheckUrlAccessForPrincipal方法.但是,对于使用授权属性保护的Action方法的URL不起作用.我想我可以弄清楚URL指向哪个方法并反映它以解决我的问题 - 但我似乎无法弄清楚如何从路由表中获取此信息.
有人曾经使用过这个,或者有解决方案吗?如果我能从URL获取路由信息,我想我可以完成其余的工作,但是如果有人有一个通用的解决方案 - 即.一些隐藏的方法类似于之前提到的MVC,然后这也是非常棒的.
我不是问如何检查用户是否有权访问指定的Controller/Action对.我首先需要弄清楚如何根据URL从RouteTable获取Controller/Action对.所有背景故事的原因都在于确实存在与UrlAuthorizationModule.CheckUrlAccessForPrincipalMVC 相当的情况.
针对MVC 4更新了上面的jfar答案:
public static class SecurityCheck
{
public static bool ActionIsAuthorized(string actionName, string controllerName)
{
IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
ControllerBase controller = factory.CreateController(HttpContext.Current.Request.RequestContext, controllerName) as ControllerBase;
var controllerContext = new ControllerContext(HttpContext.Current.Request.RequestContext, controller);
var controllerDescriptor = new ReflectedControllerDescriptor(controller.GetType());
var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
AuthorizationContext authContext = new AuthorizationContext(controllerContext, actionDescriptor);
foreach (var authAttribute in actionDescriptor.GetFilterAttributes(true).Where(a => a is AuthorizeAttribute).Select(a => a as AuthorizeAttribute))
{
authAttribute.OnAuthorization(authContext);
if (authContext.Result != null)
return false;
}
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
我从MvcSitemap移植并破解了这段代码:
public static class SecurityTrimmingExtensions
{
/// <summary>
/// Returns true if a specific controller action exists and
/// the user has the ability to access it.
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="actionName"></param>
/// <param name="controllerName"></param>
/// <returns></returns>
public static bool HasActionPermission( this HtmlHelper htmlHelper, string actionName, string controllerName )
{
//if the controller name is empty the ASP.NET convention is:
//"we are linking to a different controller
ControllerBase controllerToLinkTo = string.IsNullOrEmpty(controllerName)
? htmlHelper.ViewContext.Controller
: GetControllerByName(htmlHelper, controllerName);
var controllerContext = new ControllerContext(htmlHelper.ViewContext.RequestContext, controllerToLinkTo);
var controllerDescriptor = new ReflectedControllerDescriptor(controllerToLinkTo.GetType());
var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
return ActionIsAuthorized(controllerContext, actionDescriptor);
}
private static bool ActionIsAuthorized(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
if (actionDescriptor == null)
return false; // action does not exist so say yes - should we authorise this?!
AuthorizationContext authContext = new AuthorizationContext(controllerContext);
// run each auth filter until on fails
// performance could be improved by some caching
foreach (IAuthorizationFilter authFilter in actionDescriptor.GetFilters().AuthorizationFilters)
{
authFilter.OnAuthorization(authContext);
if (authContext.Result != null)
return false;
}
return true;
}
private static ControllerBase GetControllerByName(HtmlHelper helper, string controllerName)
{
// Instantiate the controller and call Execute
IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
IController controller = factory.CreateController(helper.ViewContext.RequestContext, controllerName);
if (controller == null)
{
throw new InvalidOperationException(
String.Format(
CultureInfo.CurrentUICulture,
"Controller factory {0} controller {1} returned null",
factory.GetType(),
controllerName));
}
return (ControllerBase)controller;
}
Run Code Online (Sandbox Code Playgroud)
它可以使用一些缓存,但对于我的情况,这是一个过早的优化.
您想要解决的问题是什么?听起来您可能会走上一条通往复杂解决方案的道路,而实际上可以使用简单的解决方案。
如果用户在登录后无权访问该页面,您是否希望未登录的用户转到一个页面,而登录的用户转到另一个页面?
如果是这种情况,我可能会想为这种情况创建另一个控制器,并重定向到用户无权访问的任何地方的控制器。或者,如果您使用自己的基本控制器,我会将功能放在那里。
然后控制器就可以呈现所需的视图。例如,如果未登录的用户尝试访问页面,他们可能会被重定向到通用错误页面。如果用户登录,他们可能会被重定向到未经授权的页面。
这与罗伯特的回答非常相似。
这是基本控制器的基本框架。
public BaseController: Controller
{
... // Some code
public ActionResult DisplayErrorPage()
{
// Assumes you have a User object with a IsLoggedIn property
if (User.IsLoggedIn())
return View("NotAuthorized");
// Redirect user to login page
return RedirectToAction("Logon", "Account");
}
}
Run Code Online (Sandbox Code Playgroud)
然后我们说一个 AdminController (继承自 BaseController)动作
public ActionResult HighlyRestrictedAction()
{
// Assumes there is a User object with a HasAccess property
if (User.HasAccess("HighlyRestrictedAction") == false)
return DisplayErrorPage();
// At this point the user is logged in and has permissions
...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
13027 次 |
| 最近记录: |