Desejo obter um usuário atual para obter informações de um usuário, como um email. Mas não posso fazer isso no núcleo do asp.net. Estou tão confuso Este é o meu código.
HttpContext
quase é nulo no construtor do controlador. Não é bom ter um usuário em cada ação. Quero obter informações do usuário uma vez e configurá-las ViewData
;
public DashboardController()
{
var user = HttpContext.User.GetUserId();
}
c#
asp.net-core
asp.net-identity
Mehran Hafizi
fonte
fonte
Respostas:
EDIT para construtor
O código abaixo funciona:
Editar para RTM
Você deve se registrar
IHttpContextAccessor
:fonte
ClaimTypes.NameIdentifier
fornece o ID do usuário atual eClaimTypes.Name
fornece o nome de usuário.null
no meu caso? Estou usando.Net core 2.1 Web api
embora.Maneira simples que funciona e eu verifiquei.
então você pode todas as propriedades dessas variáveis como
user.Email
. Espero que isso ajude alguém.Editar :
É uma coisa aparentemente simples, mas um pouco complicada, causa de diferentes tipos de sistemas de autenticação no ASP.NET Core. Eu atualizo porque algumas pessoas estão recebendo
null
.Para autenticação JWT (Testado no ASP.NET Core v3.0.0-preview7):
fonte
Tenho outra maneira de obter usuário atual no Asp.NET Core - e acho que vi em algum lugar aqui, no SO ^^
Esse código vai para o controlador chamado DemoController. Não funcionará sem que ambos esperem (não será compilado);)
fonte
Devo dizer que fiquei bastante surpreso que o HttpContext seja nulo dentro do construtor. Tenho certeza que é por razões de desempenho. Confirmaram que o uso
IPrincipal
conforme descrito abaixo injeta no construtor. É essencialmente fazer o mesmo que a resposta aceita, mas de uma maneira mais interativa.Para quem encontrar esta pergunta, procurando uma resposta para o genérico "Como obter usuário atual?" você pode simplesmente acessar
User
diretamente deController.User
. Mas você só pode fazer isso dentro dos métodos de ação (presumo que os controladores não sejam executados apenas com HttpContexts e por razões de desempenho).No entanto - se você precisar dele no construtor (como o OP fez) ou precisar criar outros objetos injetáveis que precisam do usuário atual, a seguir é apresentada uma abordagem melhor:
Injete o IPrincipal para obter o usuário
Primeiro encontro
IPrincipal
eIIdentity
IPrincipal
eIIdentity
representa o usuário e o nome de usuário. A Wikipedia o confortará se 'Principal' parecer estranho .Importante perceber que se você começar a partir de
IHttpContextAccessor.HttpContext.User
,ControllerBase.User
ouControllerBase.HttpContext.User
você está recebendo um objeto que está garantido para ser umClaimsPrincipal
objeto que implementaIPrincipal
.Não há outro tipo de usuário para o qual o ASP.NET use
User
agora (mas isso não quer dizer que outra coisa não possa ser implementadaIPrincipal
).Portanto, se você tem algo que depende do 'nome do usuário atual' que deseja injetar, deve injetar
IPrincipal
e definitivamente nãoIHttpContextAccessor
.Importante: Não perca tempo injetando
IPrincipal
diretamente no seu controlador ou método de ação - é inútil, pois jáUser
está disponível para você.Em
startup.cs
:Em seguida, no seu objeto DI que precisa do usuário, você apenas injeta
IPrincipal
para obter o usuário atual.A coisa mais importante aqui é que, se você estiver fazendo testes de unidade, não precisará enviar um
HttpContext
, mas precisará simular algo que represente oIPrincipal
que pode serClaimsPrincipal
.Uma coisa extra importante que eu não tenho 100% de certeza. Se você precisar acessar as reivindicações reais,
ClaimsPrincipal
precisará converterIPrincipal
paraClaimsPrincipal
. Isso é bom, pois sabemos 100% que, em tempo de execução, é desse tipo (já que é isso queHttpContext.User
é). Na verdade, gosto de fazer isso no construtor, pois já tenho certeza de queIPrincipal
será umClaimsPrincipal
.Se você estiver fazendo zombaria, basta criar um
ClaimsPrincipal
diretamente e passá-lo para o que for precisoIPrincipal
.Exatamente por que não há interface,
IClaimsPrincipal
não tenho certeza. Presumo que a Microsoft tenha decidido queClaimsPrincipal
era apenas uma "coleção" especializada que não justificava uma interface.fonte
null
o injetadoIPrincipal
. Eu também precisava adicionar o serviço transitório como…GetService<IHttpContextAccessor>()?.HttpContext.User…
(com o?
) porque ele falharia caso contrário (GetService retornou nulo).services.AddTransient(provider => provider.GetService<IHttpContextAccessor>().HttpContext.User);
como HttpContext.User é um ClaimsPrincipal.Parece que, a partir de agora (abril de 2017), o seguinte funciona:
Pelo menos enquanto estiver dentro de um
Controller
fonte
=>
operador usar dessa maneira antes, é chamado de "Definição do corpo da expressão" e é descrito nesta documentação . Apenas no caso de futuras pessoas como eu estarem se perguntando.IIdentity
parastring
, como também declarado no comentário principal. A edição simplesmente corrigiu isso. Também não tenho certeza de como você chegou à sua conclusão (principalmente porque os pontos de "editor" são dados apenas a usuários com menos de 2k de reputação).Talvez eu não tenha visto a resposta, mas é assim que faço.
Você precisa alterar esses valores
Startup.cs -> ConfigureServices (...)
Controlador MVC ou API da Web
Método do controlador:
O resultado é userName, por exemplo, = Domain \ username
fonte
Meu problema foi acessar o usuário conectado como um objeto no arquivo cshtml. Considerando que você queria o usuário no ViewData, essa abordagem pode ser útil:
No arquivo cshtml
fonte
Além das respostas existentes, gostaria de acrescentar que você também pode ter uma instância de classe disponível em todo o aplicativo que contém dados relacionados ao usuário,
UserID
etc.Pode ser útil para refatoração, p. você não deseja buscar
UserID
todas as ações do controlador e declarar umUserID
parâmetro extra em todos os métodos relacionados à Camada de Serviço.Eu fiz uma pesquisa e aqui está o meu post .
Você apenas estende sua classe da qual deriva
DbContext
adicionandoUserId
propriedade (ou implementa umaSession
classe personalizada que possui essa propriedade).No nível do filtro, você pode buscar sua instância de classe e definir
UserId
valor.Depois disso, onde quer que você injete sua instância - ela terá os dados necessários (a vida útil deve ser por solicitação , para que você a registre usando o
AddScoped
método).Exemplo de trabalho:
Para mais informações, veja minha resposta .
fonte
Tomar
IdentityUser
também funcionaria. Este é um objeto de usuário atual e todos os valores do usuário podem ser recuperados.fonte
Se você estiver usando a Identidade do andaime e usando o Asp.net Core 2.2+, poderá acessar o usuário atual em uma exibição como esta:
https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity?view=aspnetcore-2.2&tabs=visual-studio
fonte
Esta é uma pergunta antiga, mas meu caso mostra que meu caso não foi discutido aqui.
Eu gosto mais da resposta de Simon_Weaver ( https://stackoverflow.com/a/54411397/2903893 ). Ele explica em detalhes como obter o nome de usuário usando IPrincipal e IIdentity. Esta resposta está absolutamente correta e eu recomendo usar essa abordagem. No entanto, durante a depuração, encontrei o problema quando o ASP.NET NÃO pode preencher corretamente o princípio do serviço . (ou em outras palavras, IPrincipal.Identity.Name é nulo)
É óbvio que, para obter o nome de usuário, a estrutura MVC deve levá-la de algum lugar. No mundo .NET, o ASP.NET ou ASP.NET Core está usando o middleware Open ID Connect. No cenário simples, os aplicativos da web autenticam um usuário em um navegador da web. Nesse cenário, o aplicativo Web instrui o navegador do usuário a entrar no Azure AD. O Azure AD retorna uma resposta de entrada através do navegador do usuário, que contém declarações sobre o usuário em um token de segurança. Para que ele funcione no código do seu aplicativo, você precisará fornecer a autoridade na qual o aplicativo da Web delega a entrada. Quando você implanta seu aplicativo Web no Serviço do Azure, o cenário comum para atender a esses requisitos é configurar o aplicativo Web: "Serviços de Aplicativo" -> YourApp -> folha "Autenticação / Autorização" -> "Autenticação do Serviço de Aplicativo" = "Ativado"https://github.com/Huachao/azure-content/blob/master/articles/app-service-api/app-service-api-authentication.md ). Acredito (este é o meu palpite) que, sob o capô deste processo, o assistente ajusta a configuração da Web "pai" desse aplicativo da Web adicionando as mesmas configurações que mostro nos parágrafos seguintes. Basicamente, o problema por que essa abordagem NÃO funciona no ASP.NET Core é porque a configuração da máquina "pai" é ignorada pelo webconfig. (isso não é 100% certo, eu apenas dou a melhor explicação que tenho). Portanto, para que eu funcione, é necessário configurá-lo manualmente no seu aplicativo.
Aqui está um artigo que explica como configurar seu aplicativo de maneira geral para usar o Azure AD. https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/tree/aspnetcore2-2
Etapa 1: registre a amostra com seu inquilino do Azure AD. (é óbvio, não quero gastar meu tempo de explicações).
Etapa 2: no arquivo appsettings.json: substitua o valor ClientID pelo ID do aplicativo que você registrou no portal de registro de aplicativos na Etapa 1. substitua o valor TenantId por comum
Etapa 3: abra o arquivo Startup.cs e, no método ConfigureServices, após a linha que contém .AddAzureAD, insira o código a seguir, que permite ao seu aplicativo entrar usuários com o ponto de extremidade do Azure AD v2.0, que é Trabalho e Escola e Contas pessoais da Microsoft.
Resumo : mostrei mais um possível problema que pode estar relacionado a um erro que explica o iniciador de tópicos. O motivo desse problema está ausente nas configurações do Azure AD (middleware Open ID). Para resolver esse problema, proponho a configuração manual "Autenticação / Autorização". A breve visão geral de como configurar isso é adicionada.
fonte
A maioria das respostas mostra como lidar melhor com
HttpContext
a documentação, que também foi com a qual eu fui.Eu queria mencionar que você deseja verificar as configurações do projeto ao depurar, o padrão é
Enable Anonymous Authentication = true
.fonte
Eu tenho minha solução
fonte