Pega o usuário atual, dentro de uma ação ApiController, sem passar o ID do usuário como parâmetro

97

Como obtemos o usuário atual, dentro de uma ação ApiController segura, sem passar o userName ou userId como um parâmetro?

Presumimos que esteja disponível, pois estamos em uma ação segura. Estar em uma ação segura significa que o usuário já se autenticou e a solicitação tem seu token de portador. Dado que o WebApi autorizou o usuário, pode haver uma maneira embutida de acessar o userId, sem ter que passá-lo como um parâmetro de ação.

Shaun Luttin
fonte
Por favor, veja esta resposta: stackoverflow.com/a/26453782/3290276 Adicionar a reivindicação resolveu
Gabriela Macias

Respostas:

149

No WebApi 2, você pode usar RequestContext.Principalde dentro de um método no ApiController

Darrel Miller
fonte
1
Não temos essa propriedade, ao que parece. Hmm. Talvez estejamos usando uma versão antiga do WebApi.
Shaun Luttin
2
@ShaunLuttin Ok, então se você está usando a API Web 1, então acredito que haja uma propriedade Prinicpal no ApiController. Este é apenas um invólucro sofisticado sobre como acessar a coleção Request.Properties. O objeto principal é armazenado nesse dicionário.
Darrel Miller
6
Só não se esqueçausing Microsoft.AspNet.Identity;
Overlord
1
@DarrelMiller existe uma maneira de obter o mesmo (digamos, contexto de solicitação) de outras partes do código (não dentro do controlador).
Ajay Aradhya
2
@AjayAradhya Somente se você passar lá. Esforços anteriores em estruturas da web mostraram que o uso de propriedades estáticas para acessar o contexto de solicitação causa todos os tipos de problemas arquitetônicos. É conveniente no início, mas causa tãããão dor a longo prazo.
Darrel Miller
36

Você também pode acessar o principal usando a Userpropriedade em ApiController.

Portanto, as duas declarações a seguir são basicamente as mesmas:

string id;
id = User.Identity.GetUserId();
id = RequestContext.Principal.Identity.GetUserId();
Patrick
fonte
15
Estou tentando usar o que você escreveu aqui, mas a função GetUserId () sempre retorna nulo. O usuário está autenticado, estou passando um token do portador e o ApiController tem o cabeçalho [Autorizar]
Joshua Ohana
A função GetUserId () retorna um ID apenas se o usuário tiver uma declaração NameIdentifier. Para obter um exemplo de como resolver isso, consulte a resposta de Oswaldo aqui: stackoverflow.com/questions/19505526
jramm
14

A dica está no controlador de conta gerado automaticamente Webapi2

Tenha esta propriedade com getter definido como

public string UserIdentity
        {
            get
            {
                var user = UserManager.FindByName(User.Identity.Name);
                return user;//user.Email
            }
        }

e para obter UserManager - Em WebApi2 -do como Romanos (leia como AccountController) faça

public ApplicationUserManager UserManager
        {
            get { return HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>(); }
        }

Deve ser compatível com IIS e modo de auto-host

Karan Bhandari
fonte
7

Nenhuma das sugestões acima funcionou para mim. O seguinte fez!

HttpContext.Current.Request.LogonUserIdentity.Name

Acho que há uma grande variedade de cenários e este funcionou para mim. Meu cenário envolveu um front-end AngularJS e um aplicativo back-end Web API 2, ambos em execução no IIS. Tive que definir os dois aplicativos para serem executados exclusivamente na autenticação do Windows.

Não há necessidade de passar nenhuma informação do usuário. O navegador e o IIS trocam as credenciais do usuário conectado e a API da Web tem acesso às credenciais do usuário sob demanda (presumo do IIS).

kannankeril
fonte
6

A resposta de Karan Bhandari é boa, mas o AccountController adicionado em um projeto é muito provavelmente a Mvc.Controller. Para converter sua resposta para uso em um ApiController, altere HttpContext.Current.GetOwinContext()para Request.GetOwinContext()e certifique-se de ter adicionado as 2 usingdeclarações a seguir :

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
Jeff Leach
fonte
5

Em .Net Core, use User.Identity.Namepara obter a declaração de Nome do usuário.

Venkatesh Muniyandi
fonte
2
User.Identity.Nameobtém o valor da afirmação do nome . Não é específico do Active Directory.
Nate Barbettini
@Nate Obrigado pelo seu comentário, eu
corrigi-
3

Se você estiver usando Asp.Identity UseManager, ele define automaticamente o valor de

RequestContext.Principal.Identity.GetUserId ()

com base no IdentityUser que você usa na criação do IdentityDbContext .

Se alguma vez você estiver implementando uma tabela de usuário personalizada e autenticação de portador de token owin, por favor, verifique minha resposta.

Como obter o contexto do usuário durante chamadas de API da Web?

Espero que ainda ajude. :)

pampi
fonte
1
string userName;
string userId;
if (HttpContext.Current != null && HttpContext.Current.User != null 
        && HttpContext.Current.User.Identity.Name != null)
{
    userName = HttpContext.Current.User.Identity.Name;
    userId = HttpContext.Current.User.Identity.GetUserId();
}

Ou, com base no comentário de Darrel Miller, talvez use isso para recuperar o HttpContext primeiro.

// get httpContext
object httpContext;
actionContext.Request.Properties.TryGetValue("MS_HttpContext", out httpContext);    

Veja também:

Como acessar HTTPContext de dentro de sua ação de API da Web

Shaun Luttin
fonte
5
Não use HttpContext, pois ele limita suas opções de hospedagem e torna seu código difícil de testar.
Darrel Miller
O objeto HttpContext não estará no dicionário se você for Auto-host ou OwinHttpListener hospedado
Darrel Miller