web-dev-qa-db-ja.com

Web API呼び出し中にユーザーコンテキストを取得する方法は?

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に変換する必要があります

15
Joshua Ohana

一般的なアプローチは、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; }
        }
}
19
jake

カスタムユーザー認証を使用し(既存のユーザーテーブルフィールドが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()に注意してください

1
pampi