C# 如何在Asp.NETWebAPI中使类对象在请求的整个生命周期内可用?
这是我的密码。我已经为有效的令牌返回用户对象编写了验证令牌的登录名。但无法找到使其在控制器之间可用的方法 我不想使用身份C# 如何在Asp.NETWebAPI中使类对象在请求的整个生命周期内可用?,c#,asp.net-web-api2,C#,Asp.net Web Api2,这是我的密码。我已经为有效的令牌返回用户对象编写了验证令牌的登录名。但无法找到使其在控制器之间可用的方法 我不想使用身份 public class CustomAuthorize : AuthorizeAttribute { private const string AUTH_TOKEN = "AuthToken"; public override Task OnAuthorizationAsync(HttpActionContext actionContext, Cancel
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);
}
}
}
public类CustomAuthorize:authorized属性
{
私有常量字符串AUTH_TOKEN=“AuthToken”;
AuthorizationAsync上的公共重写任务(HttpActionContext actionContext,CancellationToken CancellationToken)
{
AllowAnyMousAttribute AllowAnyMousAttribute=actionContext.ActionDescriptor.GetCustomAttributes().FirstOrDefault();
if(allowAnonymousAttribute!=null)
{
返回Task.FromResult(空);
}
if(actionContext.Request.Headers.Contains(AUTH_令牌))
{
var authToken=actionContext.Request.Headers.GetValues(AUTH_TOKEN).First();
var user=Utility.GetUserByToken(authToken);
如果(用户!=null)
{
//
//如何使此“用户”对象在控制器中可用
//
返回Task.FromResult(空);
}
其他的
{
actionContext.Response=actionContext.Request.CreateSponse(HttpStatusCode.Unauthorized,new CustomError(){Code=100,Message=“无效访问令牌”});
返回Task.FromResult(空);
}
}
其他的
{
actionContext.Response=actionContext.Request.CreateSponse(HttpStatusCode.Unauthorized,new CustomError(){Code=100,Message=“无效访问令牌”});
返回Task.FromResult(空);
}
}
}
请帮助…一种方法是扩展ApiController,它是控制器用作基类的部分 定义自定义控制器
public class CustomController : ApiController
{
projected User _user;
}
对于所有其他控制器,请将其用作基类,并且_user对象应该可以从所有控制器访问。您的问题有点不清楚-我假设您指的是这一行:
var user = Utility.GetUserByToken(authToken);
如果是这样,那么我可能会有一个解决办法。因此,基本问题是,您不能简单地将此变量保存在当前控制器中的位置,您需要了解您所处的环境-每次不同的用户发出请求时,都会在当前控制器中创建不同的用户模型。要在用户发出请求时访问我的应用程序中的用户模型,我执行以下操作:
首先,您需要连接到ASP.NET的请求接收过程。这可以在Global.asax.cs
文件中完成,但我更喜欢保持它的整洁,创建一个PartialGlobal
类,并将Global.asax.cs
标记为partial
从
到
然后创建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;
}
}
}
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);
}
}
UserPrincipal
类:
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;
}
}
}
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.decryptoken(凭证)代码>。在这里,我只是使用我创建的一个方法对我的令牌字符串进行解密,这样它就可以被反序列化,您可能不需要这样做
基本部分是PartialGlobal
类的最后一步:
private static void SetPrincipal(UserPrincipal principal)
{
Thread.CurrentPrincipal = principal;
if (HttpContext.Current != null)
{
HttpContext.Current.User = principal;
}
}
如果您了解用户的上下文,只需调用以下命令,即可在任何位置访问该上下文:
var principal = (UserPrincipal)HttpContext.Current.User;
在WebAPI案例中,当更多的控制器参与处理单个请求时,这是非常罕见的(对于子操作,在ASP.NETMVC中更常见一些,但我从未看到WebAPI中需要它)。您确定要在单个HTTP请求期间共享信息而不是“浏览器会话”吗?实际上,我想从user
对象中知道用户ID,以便我可以使用它进行进一步处理。感谢您的回复,但在这种情况下,需要为UserPrincipal实现IPrincipal。您可以分享UserPrincipal的代码吗?当然可以:)。更新了我的帖子。当然,没问题!如何初始化_user对象?