我怎样才能让我的访问自定义的IPrincipal更容易在ASP.NET MVC? [英] How can I make accessing my custom IPrincipal easier in ASP.NET MVC?

查看:94
本文介绍了我怎样才能让我的访问自定义的IPrincipal更容易在ASP.NET MVC?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写的,其中包含了一些额外的字段(电子邮件和用户ID,除了用户名)的自定义主要对象。

I've written a custom principal object which contains a few additional fields (email and userid in addition to the username).

为了访问这些属性,我投的Context.User对象作为我的自定义主体。

In order to access these properties I have to cast the Context.User object as my custom principal.

@Html.GetGravitarImage((User as CustomPrincipal).Email)

这定义主体创建/通过Application_AuthenticateRequest在我global.ascx反序列化。你可以看到这个问题,我问<一个href=\"http://stackoverflow.com/questions/7020323/where-can-i-store-email-and-userid-in-my-asp-net-mvc-application-so-i-dont-have\">here了解更多信息。

This custom principal is created / deserialized via the Application_AuthenticateRequest in my global.ascx. You can see this question I asked here for more information.

private void Application_AuthenticateRequest(Object source, EventArgs e)
{
    var application = (HttpApplication)source;
    var context = application.Context;

    // Get the authentication cookie
    string cookieName = FormsAuthentication.FormsCookieName;
    HttpCookie authCookie = context.Request.Cookies[cookieName];
    if (authCookie == null)
        return;

    var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
    context.User = CustomPrincipal.CreatePrincipalFromCookieData(authTicket.UserData);
}

但是,如果用户没有通过验证,那么我投地CustomPrincipal将失败,(用户为CustomPrincipal)的结果(因为它不会在上面的方法注入)将返回null,从而给我当我上面的方法试图获得的电子邮件一个空引用异常。

However, if a user isn't authenticated, then my cast to CustomPrincipal will fail (because it won't be injected in the method above) and the result of the (User as CustomPrincipal) will return null, thus giving me a null reference exception when my method above attempts to get the email.

这将是一个干净的解决这个问题?我要让我的访问自定义主体容易,不必做以下似乎繁琐的:

What would be a clean solution to this problem? I want to make accessing my custom principal easy and having to do the following seems cumbersome:

@Html.GetGravitarIcon((User is CustomPrincipal) ? (User as CustomPrincipal).Email : "Default Email")

这是处理这种情况的唯一途径?

Is this the only way to handle this situation?

推荐答案

我掀起的东西很快在一起。容易引入ASP.NET MVC中一个自定义的IPrincipal一个可能的方法如下:

I whipped something together quickly. One possible way of easily introducing a custom IPrincipal in ASP.NET MVC is the following:

1)创建自己的IPrincipal接口的后代。

1) Create your own descendant of the IPrincipal interface.

public interface IMyPrincipal : IPrincipal
{
    Guid UserId { get; }
    string EmailAddress { get; }
}

2)假设你正在使用ASP.NET成员提供程序用户进行身份验证。让我们快速建立一个IMyPrincipal实现,它利用会员API。

2) Let's assume you are using the ASP.NET Membership provider to authenticate your users. Let's quickly build an IMyPrincipal implementation which utilizes the membership API.

public class MyPrincipal : IMyPrincipal
{
    private MembershipUser _user;

    public MyPrincipal()
    {
        this._user = Membership.GetUser();
        var userName = this._user != null ? this._user.UserName : String.Empty;
        this.Identity = new GenericIdentity(userName);
    }

    public Guid UserId
    {
        get 
        { 
            return this._user != null ? (Guid) this._user.ProviderUserKey : 
                                        default(Guid);
        }
    }

    public string EmailAddress
    {
        get 
        { 
            return this._user != null ? this._user.Email : null;
        }
    }

    public IIdentity Identity { get; private set; }
    public bool IsInRole(string role) { return false; }
}

3)为您的控制器创建自己的基类。隐藏继承的用户成员,并介绍自己的IPrincipal后裔。

3) Create your own base class type for your controllers. Hide the inherited User member and introduce your own IPrincipal descendant.

public class BaseController : Controller
{
    protected virtual new MyPrincipal User
    {
        get { return HttpContext.User as MyPrincipal; }
    }
}   

4)让所有的控制器从这个新的BaseController类型的下降。

4) Have all your controllers descend from this new BaseController type.

public class HomeController : BaseController
{
  //...
}

5)创建自己的控制器工厂,以确保您的本金上的HttpContext /线程出台。

5) Create your own controller factory to make sure your principal is introduced on the HttpContext / Thread.

public class MyControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance
        (RequestContext requestContext, Type controllerType)
    {
        try
        {
            var controller = base.GetControllerInstance(requestContext, controllerType);
            requestContext.HttpContext.User = Thread.CurrentPrincipal = new 
                                                    MyPrincipal();
            return controller;
        }
        catch (Exception)
        {
            return base.GetControllerInstance(requestContext, controllerType);
        }
    }
}

6)在Global.asax的的Application_Start()事件处理注册控制器工厂。

6) Register the controller factory in the Global.asax's Application_Start() event handler.

var controllerFactory = new MyControllerFactory();
ControllerBuilder.Current.SetControllerFactory(controllerFactory);

瞧,现在你可以使用新的用户(IMyPrincipal)在控制器的任何地方。

Voila, now you can use the new User (IMyPrincipal) anywhere in your controllers.

例如:

public ActionResult Index()
{
    ViewBag.Message = "Welcome to ASP.NET MVC!";

    ViewBag.UserId = User.UserId;
    ViewBag.UserName = User.EmailAddress;

    return View();
}

这篇关于我怎样才能让我的访问自定义的IPrincipal更容易在ASP.NET MVC?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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