如何在Asp .Net Web API中的请求的整个生命周期中使类对象可用?

时间:2018-02-19 07:42:48

标签: c# asp.net-web-api2

这是我的代码。我已经写了登录来验证令牌,用于有效的令牌返回用户对象。但无法找到让控制器可用的方法。

我不想使用身份。

public class CustomAuthorize : AuthorizeAttribute
{
    private const string AUTH_TOKEN = "AuthToken";

    public override Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
    {
        AllowAnonymousAttribute allowAnonymousAttribute = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().FirstOrDefault();

        if (allowAnonymousAttribute != null)
        {
            return Task.FromResult<object>(null);
        }

        if (actionContext.Request.Headers.Contains(AUTH_TOKEN))
        {
            var authToken = actionContext.Request.Headers.GetValues(AUTH_TOKEN).First();
            var user = Utility.GetUserByToken(authToken);

            if (user != null)
            {
                //
                // how to make this `user` object available across the controllers
                //

                return Task.FromResult<object>(null);
            }
            else
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, new CustomError() { Code = 100, Message = "Invalid Access Token" });
                return Task.FromResult<object>(null);
            }
        }
        else
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, new CustomError() { Code = 100, Message = "Invalid Access Token" });
            return Task.FromResult<object>(null);
        }
    }
}

请帮忙......

2 个答案:

答案 0 :(得分:1)

您的问题有点不清楚 - 我假设您指的是这一行:

var user = Utility.GetUserByToken(authToken);

如果是这样,那么我可能会有一个解决方案。所以基本的问题是你不能简单地将这个变量保存在你当前在当前控制器中的位置,你需要了解你正在使用的上下文 - 每次不同的用户发出请求时,在当前控制器中创建不同的用户模型。要在用户发出请求时在我的应用中访问用户模型,请执行以下操作:

首先,您需要挂钩ASP.NET的请求接收过程。这可以在Global.asax.cs文件中完成,但我更喜欢保持干净并创建PartialGlobal类并将Global.asax.cs标记为部分。

public class MvcApplication : System.Web.HttpApplication

public partial class MvcApplication : System.Web.HttpApplication

然后创建PartialGlobal类:

 public partial class MvcApplication
{
    protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
    {
        var request = HttpContext.Current.Request;
        var authHeader = request.Headers["Authorization"];

        //For API users
        if (authHeader != null)
        {
            var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader);
            if (authHeaderVal.Scheme.Equals("Basic", StringComparison.OrdinalIgnoreCase))
            {
                if (!string.IsNullOrEmpty(authHeaderVal.Parameter))
                {
                    AuthenticateUser(authHeaderVal.Parameter);
                }
            }
        }
        //For Regular Website Users
        else
        {
            HttpCookie authCookie = request.Cookies[FormsAuthentication.FormsCookieName];
            if (authCookie != null)
            {
                //Extract the forms authentication cookie
                FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
                // If caching userData field then extract
                var userModel = UsersBLL.DeserializeObject(authTicket.UserData);
                var principal = new UserPrincipal(userModel);
                SetPrincipal(principal);
            }
        }
    }

    private static bool AuthenticateUser(string credentials)
    {
        var model = UsersBLL.DecryptToken(credentials);
        if (!model.RefUser.HasValue)
        {
            return false;
        }

        SetPrincipal(new UserPrincipal(model));

        return true;
    }

    private static void SetPrincipal(UserPrincipal principal)
    {
        Thread.CurrentPrincipal = principal;
        if (HttpContext.Current != null)
        {
            HttpContext.Current.User = principal;
        }
    }
}    

UserPrincipal班级:

public class UserPrincipal : IPrincipal
{
    public IIdentity Identity { get; private set; }
    //Just a class with details like name,age etc.
    public UserModel Model { get; set; }

    public UserPrincipal(UserModel model)
    {
        this.Model = model;
        this.Identity = new GenericIdentity(model.Email);
    }        
}

请注意PartialGLobal班级中的一行:var model = UsersBLL.DecryptToken(credentials);。在这里,我只使用我创建的方法来解密我的令牌字符串,以便可以反序列化,您可能不会/需要这个。

关键部分是PartialGlobal类的最后一步:

private static void SetPrincipal(UserPrincipal principal)
{
     Thread.CurrentPrincipal = principal;
     if (HttpContext.Current != null)
     {
         HttpContext.Current.User = principal;
     }
}

如果您已了解用户的相关信息,只需致电:

即可随时随地访问该用户
var principal = (UserPrincipal)HttpContext.Current.User;

答案 1 :(得分:0)

一种方法是扩展ApiController,这是你的控制器用作基类的。

定义CustomController

public class CustomController : ApiController
{
    projected User _user;

}

对于所有其他控制器,将其用作基类,并且可以从所有控制器访问_user对象。