我有一个组件可以检查当前登录的用户是否可以访问控制器的操作。
public class ControllerAccessChecker : IControllerAccessChecker
{
ILifetimeScope _scope;
public ControllerAccessChecker(ILifetimeScope scope)
{
_scope = scope;
}
public bool IsAccessible<TController>(Expression<Action<TController>> action, RequestContext requestContext) where TController : Controller
{
var actionName = GetActionName(action);
var result = false;
using (var childScope = _scope.BeginLifetimeScope())
{
var controller = childScope.Resolve<TController>();
result = HasActionPermission(requestContext, actionName, controller);
}
return result;
}
private static string GetActionName(LambdaExpression actionExpression)
{
object operand;
if (actionExpression.Body as UnaryExpression != null)
{
operand = ((UnaryExpression)actionExpression.Body).Operand;
}
else
{
operand = actionExpression.Body;
}
MethodCallExpression methodCallExpression = (MethodCallExpression)operand;
return methodCallExpression.Method.Name;
}
private static bool HasActionPermission(RequestContext requestContext, string actionName, ControllerBase controller)
{
var controllerContext = new ControllerContext(requestContext, controller);
var controllerDescriptor = new ReflectedControllerDescriptor(controller.GetType());
var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
return ActionIsAuthorized(controllerContext, actionDescriptor);
}
private static bool ActionIsAuthorized(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
if (actionDescriptor == null)
return false;
AuthorizationContext authContext = new AuthorizationContext(controllerContext, actionDescriptor);
foreach (Filter authFilter in FilterProviders.Providers.GetFilters(controllerContext, actionDescriptor).Where(x => x.Instance is IAuthorizationFilter))
{
((IAuthorizationFilter)authFilter.Instance).OnAuthorization(authContext);
if (authContext.Result != null)
return false;
}
return true;
}
}
如您所见,我正在注入ILifetimeScope
构造函数,但我不确定这是否是一种好习惯。另外我不确定我是否在IsAccessible
方法中做正确的事情。这种 Autofac 的作用域层次方法让我很困惑。
我在考虑某种控制器的抽象工厂,但用 Autofac 实现似乎并不容易。IIndex<,>
我在这里找到了一些关于使用和注册的文章和答案,.Keyed()
但我不认为这真的是在这种情况下应该使用的。我的意思是我知道我需要什么类型,所以只要提出要求就应该很容易。