asp.net - 如何全局创建 CustomPrincipal(有和没有 AuthorizeAttribute)

标签 asp.net asp.net-mvc forms-authentication iprincipal

我的 ASP.NET MVC4 Web 应用程序有一个自定义主体/身份。我还创建了一个 AuthorizeAttribute 来实例化我的自定义主体,将其分配给我需要身份验证的 Controller 中的 httpContext.User。

这对于使用我的 AuthorizeAttribute 修饰的 Controller /操作非常有用但是,对于不需要身份验证的 Controller (但如果存在,仍然使用它),我想获取我的 CustomPrincipal(最好通过 HttpContext.User) .

在这些未修饰的 Controller /操作中,设置了 HttpContext.User,但使用的是 GenericPrincipal 而不是我的 CustomPrincipal。 将 HttpContext.User 的默认设置“覆盖”到 GenericPrincipal 的最佳位置在哪里?

同样,如果在每个具有身份验证 cookie 的请求中都这样做,在 AuthorizeAttribute 修饰的 Controller 的情况下,我将如何避免做两次工作(这将成为一个强制认证)。

为了清楚起见,我的网站允许匿名用户访问,但在这些页面上,如果一个经过身份验证(并且实现了 CustomPrincipal),则提供了额外的功能。

我认为一些选项是(不确定每个选项背后的逻辑):

  • 使用 session (并处理逻辑来创建我需要的东西,忘记校长)
  • Application_AuthenticateRequest - 在网上看到评论说这是老派
  • 在基本 Controller 上设置的自定义过滤器
  • 在基本 Controller 上创建一个 AuthorizationAttribute,让每个人都可以通过并根据需要设置 HttpContext.User
  • IHttpModule - 这似乎是一种下降方式(除非其他人不同意,否则沿着这条路前进)。

  • 想法?

    最佳答案

    您可以使用全局操作过滤器。假设您有一个自定义主体:

    public class MyPrincipal : GenericPrincipal
    {
        public MyPrincipal(IIdentity identity, string[] roles): base(identity, roles)
        {
        }
    
        ... some custom properties and stuff
    }
    

    那么你可以编写一个全局授权操作过滤器(但它不是从基础 AuthorizeAttribute 派生来避免全局身份验证,它只是实现了 IAuthorizationFilter 接口(interface)以确保它在任何其他过滤器之前运行):
    public class GlobalIdentityInjector : ActionFilterAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            var identity = filterContext.HttpContext.User.Identity;
    
            // do some stuff here and assign a custom principal:
            var principal = new MyPrincipal(identity, null);
            // here you can assign some custom property that every user 
            // (even the non-authenticated have)
    
            // set the custom principal
            filterContext.HttpContext.User = principal;
        }
    }
    

    全局过滤器将在 ~/App_Start/FilterConfig.cs 中注册以便保证它将适用于所有操作:
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new GlobalIdentityInjector());
        }
    }
    

    现在您可以拥有一个自定义授权属性,该属性仅适用于某些需要身份验证的 Controller 操作:
    public class MyAuthorizeAttribute : AuthorizeAttribute
    {
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            var authorized = base.AuthorizeCore(httpContext);
            if (!authorized)
            {
                return false;
            }
    
            // we know that at this stage we have our custom
            // principal injected by the global action filter
            var myPrincipal = (MyPrincipal)httpContext.User;
    
            // do some additional work here to enrich this custom principal
            // by setting some other properties that apply only to
            // authenticated users
    
            return true;
    
        }
    }
    

    然后你可以有两种类型的 Action :
    public ActionResult Foo()
    {
        var user = (MyPrincipal)User;
    
        // work with the custom properties that apply only
        // to anonymous users
    
        ...
    }
    
    [MyAuthorize]
    public ActionResult Bar()
    {
        var user = (MyPrincipal)User;
    
        // here you can work with all the properties
        // because we know that the custom authorization
        // attribute set them and the global filter set the other properties
    
        ...
    }
    

    关于asp.net - 如何全局创建 CustomPrincipal(有和没有 AuthorizeAttribute),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11476301/

    相关文章:

    c# - 从 ListView 控件获取索引项

    c# - 使用 TimeSpan.Parse 的 QueryExtender Linq Orderby

    asp.net-mvc - 我可以修改 Html.DisplayFor 以显示任何字符的子字符串吗

    asp.net - 为什么将表单例份验证超时设置为比 session 超时长?

    c# - 将某些页面功能或用户界面限制为 Asp.Net 中经过身份验证的用户

    asp.net-mvc-3 - IIS 7+ MVC 静态内容未在登录页面上呈现(对于未经身份验证的用户)

    c# - .net 4.0 中是否可以拥有动态对象属性

    c# - 从 MVC 区域重定向将我重定向到顶级操作?

    c# - 在 C# 中使用 LINQ 的条件过滤器

    jquery - asp mvc2,如何发布和绑定(bind)嵌套对象?