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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在Asp .Net Web API中的请求的整个生命周期中使类对象可用?相关的知识,希望对你有一定的参考价值。

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

我不想使用Identity。

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);
        }
    }
}

请帮忙...

答案

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

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;
另一答案

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

定义自定义控制器

public class CustomController : ApiController
{
    projected User _user;

}

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

以上是关于如何在Asp .Net Web API中的请求的整个生命周期中使类对象可用?的主要内容,如果未能解决你的问题,请参考以下文章

无需 api 或 web 服务调用即可集成 asp.net 服务

Web API系列教程2.1 — ASP.NET Web API中的路由机制

Web API系列教程2.2 — ASP.NET Web API中的路由和动作选择机制

如何在 ASP.NET Core MVC 中请求和显示实时 Web api 数据?

下载文件请求返回 JSON 而不是服务器上 ASP.NET Web API 中的文件

试图从asp.net web api self host中的请求中获取用户代理