坚持创建与QUOT;安全修整" html.ActionLink扩展方法 [英] Stuck creating a "security trimmed" html.ActionLink extension method
问题描述
我试图创建一个扩展方法对MVC的的HtmlHelper。
其目的是启用或禁用基础上,AuthorizeAttribute在控制器/动作设置ActionLink的。
从<借款href=\"http://blog.maartenballiauw.be/post/2008/08/29/Building-an-ASPNET-MVC-sitemap-provider-with-security-trimming.aspx\"相对=nofollow> MVCSitemap
这马腾Balliauw创建code,我想在决定如何渲染ActionLink的前验证用户对控制器/操作的权限。
当我试图让MvcHandler,我得到一个空值。
有没有更好的方式来为控制器/动作的属性?
下面是code的扩展方法:
公共静态类HtmlHelperExtensions
{
公共静态字符串SecurityTrimmedActionLink(此的HtmlHelper的HtmlHelper,LINKTEXT串,串动,串控制器)
{
//简化为简洁
如果(IsAccessibleToUser(动作,控制器))
{
返回htmlHelper.ActionLink(LINKTEXT,动作,控制器);
}
其他
{
返回的String.Format(&LT;跨度&GT; {0}&LT; / SPAN&gt;中,LINKTEXT);
}
} 公共静态布尔IsAccessibleToUser(串动,串控制器)
{
HttpContext的背景下= HttpContext.Current; MvcHandler处理器= context.Handler为MvcHandler; 一个IController verifyController =
ControllerBuilder类
。当前
.GetControllerFactory()
.CreateController(handler.RequestContext,控制器); [对象] controllerAttributes = verifyController.GetType()GetCustomAttributes(typeof运算(AuthorizeAttribute),TRUE)。
[对象] actionAttributes = verifyController.GetType()实现getMethod(动作).GetCustomAttributes(typeof运算(AuthorizeAttribute),TRUE)。 如果(controllerAttributes.Length == 0安培;&安培; actionAttributes.Length == 0)
返回true; 主要的IPrincipal = handler.RequestContext.HttpContext.User; 串角色=;
字符串用户=;
如果(controllerAttributes.Length大于0)
{
AuthorizeAttribute属性= controllerAttributes [0]作为AuthorizeAttribute;
角色+ = attribute.Roles;
用户+ = attribute.Users;
}
如果(actionAttributes.Length大于0)
{
AuthorizeAttribute属性= actionAttributes [0]作为AuthorizeAttribute;
角色+ = attribute.Roles;
用户+ = attribute.Users;
} 如果(string.IsNullOrEmpty(角色)及&放大器; string.IsNullOrEmpty(用户)及&放大器; principal.Identity.IsAuthenticated)
返回true; 串[] roleArray = roles.Split(,);
串[] usersArray = users.Split(,);
的foreach(在roleArray串角色)
{
如果(角色=*&放大器;!&安培;!principal.IsInRole(角色))返回false;
}
的foreach(在usersArray字符串用户)
{
如果(用户=*&放大器;!及(principal.Identity.Name ==|| principal.Identity.Name =用户)!)返回false;
}
返回true;
}}
下面是工作code:
使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用的System.Web;
使用System.Security.Principal;
使用System.Web.Routing;
使用System.Web.Mvc;
System.Collections中使用;
使用的System.Reflection;
命名空间System.Web.Mvc.Html
{
公共静态类HtmlHelperExtensions
{
公共静态字符串SecurityTrimmedActionLink(
这个的HtmlHelper的HtmlHelper,
串LINKTEXT,
串动,
串控制器)
{
返回SecurityTrimmedActionLink(的HtmlHelper,LINKTEXT,动作,控制器,FALSE);
}
公共静态字符串SecurityTrimmedActionLink(此的HtmlHelper的HtmlHelper,LINKTEXT串,串动,串控制器,布尔showDisabled)
{
如果(IsAccessibleToUser(动作,控制器))
{
返回htmlHelper.ActionLink(LINKTEXT,动作,控制器);
}
其他
{
返回showDisabled?的String.Format(&LT;跨度&GT; {0}&LT; / SPAN&gt;中,LINKTEXT):;
}
}
公共静态布尔IsAccessibleToUser(字符串actionAuthorize,串controllerAuthorize)
{
装配装配= Assembly.GetExecutingAssembly();
GetControllerType(controllerAuthorize);
键入controllerType = GetControllerType(controllerAuthorize);
VAR控制器=(一个IController)Activator.CreateInstance(controllerType);
ArrayList的controllerAttributes =新的ArrayList(controller.GetType()GetCustomAttributes(typeof运算(AuthorizeAttribute),真));
ArrayList的actionAttributes =新的ArrayList();
MethodInfo的[] =方法controller.GetType()的getMethods()。
的foreach(在方法MethodInfo的方法)
{
[对象]属性= method.GetCustomAttributes(typeof运算(ActionNameAttribute),TRUE);
如果((attributes.Length == 0安培;&安培; method.Name == actionAuthorize)||(attributes.Length大于0和放大器;及((ActionNameAttribute)属性[0])名称== actionAuthorize)。)
{
actionAttributes.AddRange(method.GetCustomAttributes(typeof运算(AuthorizeAttribute),真));
}
}
如果(controllerAttributes.Count == 0安培;&安培; actionAttributes.Count == 0)
返回true; 主要的IPrincipal = HttpContext.Current.User;
串角色=;
字符串用户=;
如果(controllerAttributes.Count大于0)
{
AuthorizeAttribute属性= controllerAttributes [0]作为AuthorizeAttribute;
角色+ = attribute.Roles;
用户+ = attribute.Users;
}
如果(actionAttributes.Count大于0)
{
AuthorizeAttribute属性= actionAttributes [0]作为AuthorizeAttribute;
角色+ = attribute.Roles;
用户+ = attribute.Users;
} 如果(string.IsNullOrEmpty(角色)及&放大器; string.IsNullOrEmpty(用户)及&放大器; principal.Identity.IsAuthenticated)
返回true; 串[] roleArray = roles.Split(,);
串[] usersArray = users.Split(,);
的foreach(在roleArray串角色)
{
如果(角色==*|| principal.IsInRole(角色))
返回true;
}
的foreach(在usersArray字符串用户)
{
如果(用户==*&放大器;及(principal.Identity.Name ==用户))
返回true;
}
返回false;
} 公共静态类型GetControllerType(字符串controllerName)
{
装配装配= Assembly.GetExecutingAssembly();
的foreach(在assembly.GetTypes类型类型())
{
如果(type.BaseType.Name ==控制器和放大器;及(type.Name.ToUpper()==(controllerName.ToUpper()+控制器.ToUpper())))
{
返回类型;
}
}
返回null;
}
}
}
我不喜欢使用反射,但我不能获取到ControllerTypeCache。
I'm trying to create an Extension Method for MVC's htmlHelper.
The purpose is to enable or disable an ActionLink based on the AuthorizeAttribute set on the controller/action.
Borrowing from the MVCSitemap
code that Maarten Balliauw created, I wanted to validate the user's permissions against the controller/action before deciding how to render the actionlink.
When I try to get the MvcHandler, I get a null value.
Is there a better way to the the attributes for the controller/action?
Here is the code for the extension method:
public static class HtmlHelperExtensions
{
public static string SecurityTrimmedActionLink(this HtmlHelper htmlHelper, string linkText, string action, string controller)
{
//simplified for brevity
if (IsAccessibleToUser(action, controller))
{
return htmlHelper.ActionLink(linkText, action,controller);
}
else
{
return String.Format("<span>{0}</span>",linkText);
}
}
public static bool IsAccessibleToUser(string action, string controller)
{
HttpContext context = HttpContext.Current;
MvcHandler handler = context.Handler as MvcHandler;
IController verifyController =
ControllerBuilder
.Current
.GetControllerFactory()
.CreateController(handler.RequestContext, controller);
object[] controllerAttributes = verifyController.GetType().GetCustomAttributes(typeof(AuthorizeAttribute), true);
object[] actionAttributes = verifyController.GetType().GetMethod(action).GetCustomAttributes(typeof(AuthorizeAttribute), true);
if (controllerAttributes.Length == 0 && actionAttributes.Length == 0)
return true;
IPrincipal principal = handler.RequestContext.HttpContext.User;
string roles = "";
string users = "";
if (controllerAttributes.Length > 0)
{
AuthorizeAttribute attribute = controllerAttributes[0] as AuthorizeAttribute;
roles += attribute.Roles;
users += attribute.Users;
}
if (actionAttributes.Length > 0)
{
AuthorizeAttribute attribute = actionAttributes[0] as AuthorizeAttribute;
roles += attribute.Roles;
users += attribute.Users;
}
if (string.IsNullOrEmpty(roles) && string.IsNullOrEmpty(users) && principal.Identity.IsAuthenticated)
return true;
string[] roleArray = roles.Split(',');
string[] usersArray = users.Split(',');
foreach (string role in roleArray)
{
if (role != "*" && !principal.IsInRole(role)) return false;
}
foreach (string user in usersArray)
{
if (user != "*" && (principal.Identity.Name == "" || principal.Identity.Name != user)) return false;
}
return true;
}
}
Here is the working code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Principal;
using System.Web.Routing;
using System.Web.Mvc;
using System.Collections;
using System.Reflection;
namespace System.Web.Mvc.Html
{
public static class HtmlHelperExtensions
{
public static string SecurityTrimmedActionLink(
this HtmlHelper htmlHelper,
string linkText,
string action,
string controller)
{
return SecurityTrimmedActionLink(htmlHelper, linkText, action, controller, false);
}
public static string SecurityTrimmedActionLink(this HtmlHelper htmlHelper, string linkText, string action, string controller, bool showDisabled)
{
if (IsAccessibleToUser(action, controller))
{
return htmlHelper.ActionLink(linkText, action, controller);
}
else
{
return showDisabled ? String.Format("<span>{0}</span>", linkText) : "";
}
}
public static bool IsAccessibleToUser(string actionAuthorize, string controllerAuthorize)
{
Assembly assembly = Assembly.GetExecutingAssembly();
GetControllerType(controllerAuthorize);
Type controllerType = GetControllerType(controllerAuthorize);
var controller = (IController)Activator.CreateInstance(controllerType);
ArrayList controllerAttributes = new ArrayList(controller.GetType().GetCustomAttributes(typeof(AuthorizeAttribute), true));
ArrayList actionAttributes = new ArrayList();
MethodInfo[] methods = controller.GetType().GetMethods();
foreach (MethodInfo method in methods)
{
object[] attributes = method.GetCustomAttributes(typeof(ActionNameAttribute), true);
if ((attributes.Length == 0 && method.Name == actionAuthorize) || (attributes.Length > 0 && ((ActionNameAttribute)attributes[0]).Name == actionAuthorize))
{
actionAttributes.AddRange(method.GetCustomAttributes(typeof(AuthorizeAttribute), true));
}
}
if (controllerAttributes.Count == 0 && actionAttributes.Count == 0)
return true;
IPrincipal principal = HttpContext.Current.User;
string roles = "";
string users = "";
if (controllerAttributes.Count > 0)
{
AuthorizeAttribute attribute = controllerAttributes[0] as AuthorizeAttribute;
roles += attribute.Roles;
users += attribute.Users;
}
if (actionAttributes.Count > 0)
{
AuthorizeAttribute attribute = actionAttributes[0] as AuthorizeAttribute;
roles += attribute.Roles;
users += attribute.Users;
}
if (string.IsNullOrEmpty(roles) && string.IsNullOrEmpty(users) && principal.Identity.IsAuthenticated)
return true;
string[] roleArray = roles.Split(',');
string[] usersArray = users.Split(',');
foreach (string role in roleArray)
{
if (role == "*" || principal.IsInRole(role))
return true;
}
foreach (string user in usersArray)
{
if (user == "*" && (principal.Identity.Name == user))
return true;
}
return false;
}
public static Type GetControllerType(string controllerName)
{
Assembly assembly = Assembly.GetExecutingAssembly();
foreach (Type type in assembly.GetTypes())
{
if (type.BaseType.Name == "Controller" && (type.Name.ToUpper() == (controllerName.ToUpper() + "Controller".ToUpper())))
{
return type;
}
}
return null;
}
}
}
I don't like using reflection, but I can't get to the ControllerTypeCache.
这篇关于坚持创建与QUOT;安全修整&QUOT; html.ActionLink扩展方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!