如何在全球范围内建立一个CustomPrincipal(有和没有AuthorizeAttribute) [英] How to create a CustomPrincipal globally (with and without AuthorizeAttribute)

查看:253
本文介绍了如何在全球范围内建立一个CustomPrincipal(有和没有AuthorizeAttribute)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义主/身份对我的ASP.NET MVC4 web应用程序。我还创建了一个AuthorizeAttribute实例我自定义的校长,在我需要验证控制器将其分配给HttpContext.User中。

I have a custom Principal/Identity for my ASP.NET MVC4 web app. I have also created a AuthorizeAttribute to instantiate my custom principal, assigning it to httpContext.User in controllers where I require Authentication.

这对已装饰着我的AuthorizeAttribute,然而,对于那些不要求身份验证(但仍使用它,如果它是存在的),我希望得到我的CustomPrincipal控制器(控制器/行动的伟大工程和$ p $通过HttpContext.User中pferably)

This works great for controller/actions that have been decorated with my AuthorizeAttribute, however, for controllers that don't require authentication (but still use it if it is there), I would like to get my CustomPrincipal (and preferably through HttpContext.User).

在这些非装饰控制器/动作,HttpContext.User中被设置,但与的GenericPrincipal而不是与我的CustomPrincipal。 将在什么地方最好的地方,'覆盖'一个HttpContext.User中到的GenericPrincipal?

In these non-decorated controller/actions, HttpContext.User is set, but with a GenericPrincipal rather than with my CustomPrincipal. Where would the best place to 'override' the default setting of a HttpContext.User to the GenericPrincipal?

同时,如果这是在一个具有权威性的cookie,每个请求我怎么会那么避免在AuthorizeAttribute装饰控制器的情况下做的工作做两次(那么这将只是成为一体该授权认证)。

As well, if this is done in every request that has an auth cookie, how would I then avoid doing the work twice in the case of a AuthorizeAttribute decorated controller (which would then just become one that mandated authentication).

只是要清楚,我的网站允许匿名用户访问,但在这些页面上,如果一个被认证(和CustomPrincipal实现),提供额外的功能。

Just to be clear, my site allows anonymous users access, but on those pages, if one is authenticated (and a CustomPrincipal is realized), there are extra features provided.

我觉得有些选项(不能确定我的背后逻辑,每一个):

I think some of the options are (not certain of my logic behind each one):


  • 使用一个会话(和处理逻辑来创造什么我需要在这里,忘记了校长)

  • Application_AuthenticateRequest - 看到了网络上的评论,这是老同学

  • 一个基本控制器上设置自定义过滤器

  • 主控制器,通过让每个人都并设置HttpContext.User中,因为我想上创建一个AuthorizationAttribute它

  • IHttpModule的 - 这似乎是一个下降的方式(和航向沿着这条道路,除非其他人不同意)

思考?

推荐答案

您可以使用全球行动过滤器。让我们假设你有一个自定义主体:

You could use a global action filter. Let's suppose that you have a custom principal:

public class MyPrincipal : GenericPrincipal
{
    public MyPrincipal(IIdentity identity, string[] roles): base(identity, roles)
    {
    }

    ... some custom properties and stuff
}

然后你可以写一个全局授权行动过滤器(但不从基 AuthorizeAttribute 来避免全球认证派生,它只是实现了个IAuthorizationFilter 接口,以保证它的任何其他过滤器之前运行):

then you could write a global authorization action filter (but which doesn't derive from the base AuthorizeAttribute to avoid global authentication, it just implements the IAuthorizationFilter interface to ensure that it runs before any other filters):

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 中注册,这样可以保证它适用于所有操作:

The global filter will be registered in ~/App_Start/FilterConfig.cs so that it is guaranteed that it will apply to all actions:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new GlobalIdentityInjector());
    }
}

现在,你可以有这将只适用于那些需要验证某些控制器操作的自定义授权属性:

And now you could have a custom authorization attribute which will be applied only to certain controller actions that require authentication:

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;

    }
}

然后你可以有2种类型的动作:

and then you could have 2 types of actions:

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

    ...
}

这篇关于如何在全球范围内建立一个CustomPrincipal(有和没有AuthorizeAttribute)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆