如何在 Web Api 调用期间获取用户上下文?
How to get user context during Web Api calls?
我有一个 Web 前端调用 ASP Web Api 2 后端。使用 ASP 身份管理身份验证。对于我正在创建的一些控制器,我需要知道发出呼叫的用户。我不想创建一些奇怪的模型来传递,包括用户的身份(我什至不存储在客户端中)。
所有对 API 的调用都使用不记名令牌授权,我的想法是控制器应该能够基于此确定用户上下文,但我不知道如何实现。我已经搜索过,但我不知道我在搜索什么,也没有找到任何相关的东西。我要去的东西...
public async Task<IHttpActionResult> Post(ApplicationIdentity identity, WalkthroughModel data)
更新
我发现下面看起来很有希望...但值始终为空!我的控制器继承自 ApiController 并且有一个 Authorize header.
var userid = User.Identity.GetUserId();
更新 2
我也尝试了 Get the current user, within an ApiController action, without passing the userID as a parameter 中的所有解决方案,但 none 有效。不管我得到一个有效和授权的身份,但有一个空的 UserID
更新 3
这是我现在所在的位置。
[Authorize]
[Route("Email")]
public async Task<IHttpActionResult> Get()
{
var testa = User.Identity.GetType();
var testb = User.Identity.GetUserId();
var testc = User.Identity.AuthenticationType;
var testd = User.Identity.IsAuthenticated;
return Ok();
}
testa = Name: ClaimsIdentity,
testb = null,
testc = Bearer,
testd = true
用户显然已通过身份验证,但我无法检索他们的用户 ID。
更新 4
我找到了答案,但我真的很不满意...
ClaimsIdentity identity = (ClaimsIdentity)User.Identity;
string username = identity.Claims.First().Value;
这让我在没有任何数据库调用的情况下获得了用户名,但它看起来非常笨拙,并且在未来支持起来很痛苦。如果有人有更好的答案,我会很高兴。
如果我需要更改以后发出的声明怎么办?另外,任何时候我实际上需要用户的 ID 时,我都必须进行数据库调用以将用户名转换为 ID
一种常见的方法是为您的 ApiControllers 创建一个基础 class 并利用 ApplicationUserManager 来检索您需要的信息。使用这种方法,您可以将访问用户信息的逻辑保留在一个位置,并在您的控制器中重复使用它。
public class BaseApiController : ApiController
{
private ApplicationUser _member;
public ApplicationUserManager UserManager
{
get { return HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>(); }
}
public string UserIdentityId
{
get
{
var user = UserManager.FindByName(User.Identity.Name);
return user.Id;
}
}
public ApplicationUser UserRecord
{
get
{
if (_member != null)
{
return _member ;
}
_member = UserManager.FindByEmail(Thread.CurrentPrincipal.Identity.Name);
return _member ;
}
set { _member = value; }
}
}
我使用自定义用户身份验证(我不使用 AspIdentity,因为我现有的用户 table 字段与 IdentityUser 属性有很大不同)并通过我的 table 用户 ID 和用户名创建 ClaimsIdentity 来验证我的持有人API 个调用的令牌。
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
User user;
try
{
var scope = Autofac.Integration.Owin.OwinContextExtensions.GetAutofacLifetimeScope(context.OwinContext);
_service = scope.Resolve<IUserService>();
user = await _service.FindUserAsync(context.UserName);
if (user?.HashedPassword != Helpers.CustomPasswordHasher.GetHashedPassword(context.Password, user?.Salt))
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
}
catch (Exception ex)
{
context.SetError("invalid_grant", ex.Message);
return;
}
var properties = new Dictionary<string, string>()
{
{ ClaimTypes.NameIdentifier, user.UserID.ToString() },
{ ClaimTypes.Name, context.UserName }
};
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
properties.ToList().ForEach(c => identity.AddClaim(new Claim(c.Key, c.Value)));
var ticket = new AuthenticationTicket(identity, new AuthenticationProperties(properties));
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(identity);
}
以及我如何使用 ClaimsIdentity 在 User ApiController Details 调用中检索我的用户 table 详细信息。
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[Route("Details")]
public async Task<IHttpActionResult> Details()
{
var user = await _service.GetAsync(RequestContext.Principal.Identity.GetUserId<int>());
var basicDetails = Mapper.Map<User, BasicUserModel>(user);
return Ok(basicDetails);
}
注意
ClaimTypes.NameIdentifier = GetUserId() 和 ClaimTypes.Name = GetUserName()
我有一个 Web 前端调用 ASP Web Api 2 后端。使用 ASP 身份管理身份验证。对于我正在创建的一些控制器,我需要知道发出呼叫的用户。我不想创建一些奇怪的模型来传递,包括用户的身份(我什至不存储在客户端中)。
所有对 API 的调用都使用不记名令牌授权,我的想法是控制器应该能够基于此确定用户上下文,但我不知道如何实现。我已经搜索过,但我不知道我在搜索什么,也没有找到任何相关的东西。我要去的东西...
public async Task<IHttpActionResult> Post(ApplicationIdentity identity, WalkthroughModel data)
更新
我发现下面看起来很有希望...但值始终为空!我的控制器继承自 ApiController 并且有一个 Authorize header.
var userid = User.Identity.GetUserId();
更新 2
我也尝试了 Get the current user, within an ApiController action, without passing the userID as a parameter 中的所有解决方案,但 none 有效。不管我得到一个有效和授权的身份,但有一个空的 UserID
更新 3
这是我现在所在的位置。
[Authorize]
[Route("Email")]
public async Task<IHttpActionResult> Get()
{
var testa = User.Identity.GetType();
var testb = User.Identity.GetUserId();
var testc = User.Identity.AuthenticationType;
var testd = User.Identity.IsAuthenticated;
return Ok();
}
testa = Name: ClaimsIdentity, testb = null, testc = Bearer, testd = true
用户显然已通过身份验证,但我无法检索他们的用户 ID。
更新 4
我找到了答案,但我真的很不满意...
ClaimsIdentity identity = (ClaimsIdentity)User.Identity;
string username = identity.Claims.First().Value;
这让我在没有任何数据库调用的情况下获得了用户名,但它看起来非常笨拙,并且在未来支持起来很痛苦。如果有人有更好的答案,我会很高兴。
如果我需要更改以后发出的声明怎么办?另外,任何时候我实际上需要用户的 ID 时,我都必须进行数据库调用以将用户名转换为 ID
一种常见的方法是为您的 ApiControllers 创建一个基础 class 并利用 ApplicationUserManager 来检索您需要的信息。使用这种方法,您可以将访问用户信息的逻辑保留在一个位置,并在您的控制器中重复使用它。
public class BaseApiController : ApiController
{
private ApplicationUser _member;
public ApplicationUserManager UserManager
{
get { return HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>(); }
}
public string UserIdentityId
{
get
{
var user = UserManager.FindByName(User.Identity.Name);
return user.Id;
}
}
public ApplicationUser UserRecord
{
get
{
if (_member != null)
{
return _member ;
}
_member = UserManager.FindByEmail(Thread.CurrentPrincipal.Identity.Name);
return _member ;
}
set { _member = value; }
}
}
我使用自定义用户身份验证(我不使用 AspIdentity,因为我现有的用户 table 字段与 IdentityUser 属性有很大不同)并通过我的 table 用户 ID 和用户名创建 ClaimsIdentity 来验证我的持有人API 个调用的令牌。
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
User user;
try
{
var scope = Autofac.Integration.Owin.OwinContextExtensions.GetAutofacLifetimeScope(context.OwinContext);
_service = scope.Resolve<IUserService>();
user = await _service.FindUserAsync(context.UserName);
if (user?.HashedPassword != Helpers.CustomPasswordHasher.GetHashedPassword(context.Password, user?.Salt))
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
}
catch (Exception ex)
{
context.SetError("invalid_grant", ex.Message);
return;
}
var properties = new Dictionary<string, string>()
{
{ ClaimTypes.NameIdentifier, user.UserID.ToString() },
{ ClaimTypes.Name, context.UserName }
};
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
properties.ToList().ForEach(c => identity.AddClaim(new Claim(c.Key, c.Value)));
var ticket = new AuthenticationTicket(identity, new AuthenticationProperties(properties));
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(identity);
}
以及我如何使用 ClaimsIdentity 在 User ApiController Details 调用中检索我的用户 table 详细信息。
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[Route("Details")]
public async Task<IHttpActionResult> Details()
{
var user = await _service.GetAsync(RequestContext.Principal.Identity.GetUserId<int>());
var basicDetails = Mapper.Map<User, BasicUserModel>(user);
return Ok(basicDetails);
}
注意 ClaimTypes.NameIdentifier = GetUserId() 和 ClaimTypes.Name = GetUserName()