ASP Web Api 2バックエンドを呼び出すWebフロントエンドがあります。認証はASP Identityで管理されます。作成中のコントローラーの一部については、呼び出しを行っているユーザーを知るために、ユーザーのID(クライアントには保存しません)を含む、奇妙なモデルを作成する必要はありません。
APIへのすべての呼び出しは、ベアラートークンを使用して承認されます。コントローラーはこれに基づいてユーザーコンテキストを決定できるはずですが、実装方法はわかりません。私は検索しましたが、私が正確に何を検索しているのかわかりませんし、関連するものも見つかりませんでした。次のようなものを探しています...
public async Task<IHttpActionResult> Post(ApplicationIdentity identity, WalkthroughModel data)
更新
私は非常に有望に見えた以下を見つけました...しかし、値は常にnullです!私のコントローラーはApiControllerを継承し、Authorizeヘッダーを持っています。
var userid = User.Identity.GetUserId();
更新2
また、 ユーザーIDをパラメーターとして渡さずに、ApiControllerアクション内で現在のユーザーを取得する ですべてのソリューションを試しましたが、機能しません。有効で認証されているが、UserIDがnullであるIDを取得しようとしても
アップデート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;
これにより、db呼び出しなしでユーザー名を取得できますが、将来的にサポートするのは非常に面倒で苦痛のようです。誰かがより良い答えを持っているなら、大好きです。
将来発行されるクレームを変更する必要がある場合はどうなりますか?さらに、実際にユーザーのIDが必要な場合は、db呼び出しを行ってユーザー名をIDに変換する必要があります
一般的なアプローチは、ApiControllersの基本クラスを作成し、ApplicationUserManagerを利用して必要な情報を取得することです。このアプローチを使用すると、ユーザーの情報にアクセスするためのロジックを1つの場所に保持し、コントローラー全体で再利用できます。
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; }
}
}
カスタムユーザー認証を使用し(既存のユーザーテーブルフィールドがIdentityUserプロパティとは大きく異なるため、AspIdentityは使用しません)、API呼び出しのベアラートークンを検証するためにテーブルUserIDとUserNameを渡すClaimsIdentityを作成します。
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呼び出しでユーザーテーブルの詳細を取得する方法。
[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()and ClaimTypes.Name = GetUserName()に注意してください