回答:
User.FindFirst(ClaimTypes.NameIdentifier).Value
コンストラクタの編集
以下のコードは機能します:
public Controller(IHttpContextAccessor httpContextAccessor)
{
var userId = httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value
}
RTM用に編集
登録する必要がありますIHttpContextAccessor
:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
}
ClaimTypes.NameIdentifier
現在のユーザーIDとClaimTypes.Name
ユーザー名を提供します。
null
私の場合に戻ってきますか?私は使用して.Net core 2.1 Web api
います。
動作する簡単な方法と私はチェックしました。
private readonly UserManager<IdentityUser> _userManager;
public CompetitionsController(UserManager<IdentityUser> userManager)
{
_userManager = userManager;
}
var user = await _userManager.GetUserAsync(HttpContext.User);
次に、この変数のすべてのプロパティをのようにできuser.Email
ます。これが誰かの役に立つことを願っています。
編集:
これは一見単純なことですが、ASP.NET Coreのさまざまな種類の認証システムの複雑な原因です。一部の人が入手してnull
いる原因を更新します。
JWT認証の場合(ASP.NET Core v3.0.0-preview7でテスト済み):
var email = HttpContext.User.Claims.FirstOrDefault(c => c.Type == "sub")?.Value;
var user = await _userManager.FindByEmailAsync(email);
Asp.NET Coreで現在のユーザーを取得する別の方法があります-そして私はそれをここのどこかで見たと思います^^
// Stores UserManager
private readonly UserManager<ApplicationUser> _manager;
// Inject UserManager using dependency injection.
// Works only if you choose "Individual user accounts" during project creation.
public DemoController(UserManager<ApplicationUser> manager)
{
_manager = manager;
}
// You can also just take part after return and use it in async methods.
private async Task<ApplicationUser> GetCurrentUser()
{
return await _manager.GetUserAsync(HttpContext.User);
}
// Generic demo method.
public async Task DemoMethod()
{
var user = await GetCurrentUser();
string userEmail = user.Email; // Here you gets user email
string userId = user.Id;
}
そのコードは、DemoControllerという名前のコントローラーに送られます。両方が待たないと動作しません(コンパイルされません);)
コンストラクター内でHttpContextがnullであることにかなり驚いたと言わざるを得ません。パフォーマンス上の理由からだと思います。IPrincipal
以下で説明するように使用すると、コンストラクタに注入されることが確認されています。基本的には、受け入れられた回答と同じですが、よりインターフェイス的な方法で行われます。
この質問を見つけて、一般的な「現在のユーザーを取得するにはどうすればよいですか?」User
から直接アクセスできますController.User
。しかし、これはアクションメソッドの内部でのみ実行できます(コントローラーはHttpContextsでのみ実行されないため、またパフォーマンス上の理由によります)。
ただし、(OPが行ったように)コンストラクターでそれを必要とする場合、または現在のユーザーを必要とする他の注入可能なオブジェクトを作成する必要がある場合は、以下がより良いアプローチです。
最初に会っIPrincipal
てIIdentity
public interface IPrincipal
{
IIdentity Identity { get; }
bool IsInRole(string role);
}
public interface IIdentity
{
string AuthenticationType { get; }
bool IsAuthenticated { get; }
string Name { get; }
}
IPrincipal
IIdentity
ユーザーとユーザー名を表します。「プリンシパル」が奇妙に聞こえる場合、ウィキペディアはあなたを慰めるでしょう。
かどうかをあなたからそれを得ることを認識することが重要IHttpContextAccessor.HttpContext.User
、ControllerBase.User
またはControllerBase.HttpContext.User
あなたがしていますことが保証されているオブジェクトになっClaimsPrincipal
ている実装するオブジェクトをIPrincipal
。
User
現在、ASP.NETが使用する他の種類のユーザーはありません(ただし、他の何かが実装できなかったと言っているわけではありませんIPrincipal
)。
だからあなたが注入したい「現在のユーザー名」の依存関係を持つものがある場合は、注入する必要があります IPrincipal
ありIHttpContextAccessor
ます。
重要:IPrincipal
コントローラーまたはアクションメソッドに直接注入する時間を無駄にしないでくださいUser
。既に利用できるので、それは無意味です。
でstartup.cs
:
// Inject IPrincipal
services.AddTransient<IPrincipal>(provider => provider.GetService<IHttpContextAccessor>().HttpContext.User);
次に、注入するユーザーを必要とするDIオブジェクトで IPrincipal
、現在のユーザーを取得するためにする。
ここで最も重要なことは、ユニットテストを実行している場合、を送信する必要はなくHttpContext
、ただ表すことができるものを模擬する必要があるだけですIPrincipal
ClaimsPrincipal
。
100%よくわからない、もう1つ重要なこと。実際の申し立てにアクセスする必要がある場合は、ClaimsPrincipal
にキャストIPrincipal
する必要がありますClaimsPrincipal
。実行時にそれがそのタイプであることを100%知っているので、これは問題ありません(それがそうであるためHttpContext.User
)。私は実際にこれをコンストラクタで実行するのが好きですIPrincipal
になりますClaimsPrincipal
。
モックする場合は、ClaimsPrincipal
直接作成しますをそれを任意のテイクに渡しますIPrincipal
。
なぜインターフェースがないのか正確にはわかりIClaimsPrincipal
ません。私はMSがClaimsPrincipal
インターフェースを保証しない特別な「コレクション」であると決定したと思います。
null
注射を受けIPrincipal
ます。それ以外の場合はクラッシュするため(GetServiceがnullを返す)、一時サービスを…GetService<IHttpContextAccessor>()?.HttpContext.User…
(を使用して?
)追加する必要もありました。
services.AddTransient(provider => provider.GetService<IHttpContextAccessor>().HttpContext.User);
HttpContext.UserがClaimsPrincipalであるのと同じようにできます。
現在(2017年4月)現在、次のように機能しているようです。
public string LoggedInUser => User.Identity.Name;
少なくとも中に Controller
IIdentity
への変換がない場合、コードは編集前にコンパイルできなかった可能性がありますstring
。編集は単にそれを修正しました。どのようにして結論に達したかはわかりません(特に、「editor」ポイントは2kの評判を下回るユーザーにのみ付与されるため)。
おそらく私は答えを見なかったかもしれませんが、これが私のやり方です。
これらの値を変更する必要があります
"windowsAuthentication": true, // needs to be true
"anonymousAuthentication": false, // needs to be false
Startup.cs-> ConfigureServices(...)
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
MVCまたはWeb APIコントローラー
private readonly IHttpContextAccessor _httpContextAccessor;
//constructor then
_httpContextAccessor = httpContextAccessor;
コントローラー方式:
string userName = _httpContextAccessor.HttpContext.User.Identity.Name;
結果はuserNameです。例= Domain \ username
私の問題は、cshtmlファイルのオブジェクトとして、ログインしたユーザーにアクセスすることでした。ViewDataでユーザーが必要であることを考えると、このアプローチが役立つ場合があります。
cshtmlファイル
@using Microsoft.AspNetCore.Identity
@inject UserManager<ApplicationUser> UserManager
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>
@UserManager.FindByNameAsync(UserManager.GetUserName(User)).Result.Email
</title>
</head>
<body>
</body>
</html>
既存の回答に加えて、ユーザー関連のデータUserID
などを保持するクラスインスタンスをアプリ全体で利用できるようにすることもできます。
たとえば、リファクタリング に役立つ場合があります。UserID
すべてのコントローラーアクションでフェッチしUserID
、サービスレイヤーに関連するすべてのメソッドで追加のパラメーターを宣言する必要はありません。
私は調査を行いました、そしてこれが私の投稿です。
プロパティDbContext
を追加してUserId
(またはカスタムを実装して)派生したクラスを拡張するだけです。Session
このプロパティを持つクラスを。
フィルターレベルでは、クラスインスタンスをフェッチしてUserId
値を設定できます。
その後、インスタンスを挿入する場所に-必要なデータが含まれます(ライフタイムはリクエストごとでなければならないため、AddScoped
メソッドを使用して登録します)。
作業例:
public class AppInitializationFilter : IAsyncActionFilter
{
private DBContextWithUserAuditing _dbContext;
public AppInitializationFilter(
DBContextWithUserAuditing dbContext
)
{
_dbContext = dbContext;
}
public async Task OnActionExecutionAsync(
ActionExecutingContext context,
ActionExecutionDelegate next
)
{
string userId = null;
int? tenantId = null;
var claimsIdentity = (ClaimsIdentity)context.HttpContext.User.Identity;
var userIdClaim = claimsIdentity.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier);
if (userIdClaim != null)
{
userId = userIdClaim.Value;
}
var tenantIdClaim = claimsIdentity.Claims.SingleOrDefault(c => c.Type == CustomClaims.TenantId);
if (tenantIdClaim != null)
{
tenantId = !string.IsNullOrEmpty(tenantIdClaim.Value) ? int.Parse(tenantIdClaim.Value) : (int?)null;
}
_dbContext.UserId = userId;
_dbContext.TenantId = tenantId;
var resultContext = await next();
}
}
scafolded Identityを使用し、Asp.net Core 2.2+を使用している場合は、次のようなビューから現在のユーザーにアクセスできます。
@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager
@if (SignInManager.IsSignedIn(User))
{
<p>Hello @User.Identity.Name!</p>
}
else
{
<p>You're not signed in!</p>
}
これは古い質問ですが、私のケースは私のケースがここで議論されなかったことを示しています。
私はSimon_Weaver(https://stackoverflow.com/a/54411397/2903893)の答えが一番好きです。彼はIPrincipalとIIdentityを使用してユーザー名を取得する方法を詳しく説明しています。この答えは完全に正しいので、このアプローチを使用することをお勧めします。ただし、デバッグ中に、ASP.NETがサービスプリンシパルを適切に設定できないという問題が発生しました。(つまり、IPrincipal.Identity.Nameはnullです)
ユーザー名を取得するには、MVCフレームワークがどこかから取得する必要があることは明らかです。.NETの世界では、ASP.NETまたはASP.NET CoreはOpen ID Connectミドルウェアを使用しています。単純なシナリオでは、WebアプリはWebブラウザーでユーザーを認証します。このシナリオでは、WebアプリケーションはユーザーのブラウザーにユーザーをAzure ADにサインインするように指示します。Azure ADは、ユーザーのブラウザーを介してサインインレスポンスを返します。これには、ユーザーに関するクレームがセキュリティトークンに含まれています。これをアプリケーションのコードで機能させるには、Webアプリのサインインを委任する権限を提供する必要があります。AzureサービスにWebアプリを展開する場合、この要件を満たすための一般的なシナリオは、Webアプリを構成することです: "App Services"-> YourApp-> "Authentication / Authorization"ブレード-> "App Service Authenticatio" = "On"https://github.com/Huachao/azure-content/blob/master/articles/app-service-api/app-service-api-authentication.md)。私は、このプロセスのフードの下で、ウィザードが次の段落で示すものと同じ設定を追加することにより、このWebアプリの「親」Web構成を調整すると信じています(これは私の推測です)。基本的に、このアプローチがASP.NET Coreで機能しないのは、「親」のマシン構成がwebconfigによって無視されるためです。(これは100%確実ではありません。私が持っている最良の説明をします)。したがって、それを機能させるには、アプリでこれを手動で設定する必要があります。
ここでは、Azure ADを使用するようにアプリを頻繁にセットアップする方法を説明する記事を示します。 https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/tree/aspnetcore2-2
手順1:サンプルをAzure ADテナントに登録します。(当然のことですが、説明に時間をかけたくないです)。
ステップ2:appsettings.jsonファイルで、ClientID値を、ステップ1のアプリケーション登録ポータルで登録したアプリケーションのアプリケーションIDに置き換えます。TenantId値を一般的な
手順3:Startup.csファイルを開き、ConfigureServicesメソッドで、.AddAzureADを含む行に次のコードを挿入します。これにより、アプリケーションはAzure AD v2.0エンドポイントを使用してユーザーをサインインできます。 Microsoft個人アカウント。
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
options.Authority = options.Authority + "/v2.0/";
options.TokenValidationParameters.ValidateIssuer = false;
});
要約:トピックスターターが説明されているというエラーにつながる可能性のあるもう1つの問題を示しました。この問題の理由は、Azure AD(Open IDミドルウェア)の構成がないためです。この問題を解決するために、私は手動で「認証/承認」を設定することを提案します。これを設定する方法の短い概要が追加されます。
答えのほとんどは、HttpContext
ドキュメントから最も適切に処理する方法を示しています。これは私が行ったものでもあります。
デバッグ時にプロジェクト設定を確認することをお勧めしますEnable Anonymous Authentication = true
。デフォルトはです。
私は私の解決策を得ました
var claim = HttpContext.User.CurrentUserID();
public static class XYZ
{
public static int CurrentUserID(this ClaimsPrincipal claim)
{
var userID = claimsPrincipal.Claims.ToList().Find(r => r.Type ==
"UserID").Value;
return Convert.ToInt32(userID);
}
public static string CurrentUserRole(this ClaimsPrincipal claim)
{
var role = claimsPrincipal.Claims.ToList().Find(r => r.Type ==
"Role").Value;
return role;
}
}