BlazorとWindows認証で新しいサイトを開始し、ページ/コンポーネントを表示している現在のユーザーを特定する必要があります。
Razorページの場合、現在のユーザー名にはContext.User.Identity.Name
を使用してアクセスできますが、これはBlazorコンポーネントでは機能しないようです。コンポーネントにHttpContextを挿入しようとしましたが、実行時にコンテキストがnullです。
おまけとして、これを最終的にStartup.csに組み込みたいので、ユーザー名を1回取得するだけで済み、アプリケーションで企業ユーザークラス(EF Coreを使用)を利用できます。そのユースケースに合わせた回答もいただければ幸いです。
これで、コンポーネントだけでなく、一般的なクラスでも機能するようになりました。
HttpContextユーザーにアクセスするには、 ConfigureServices、Startup.csに追加
_services.AddHttpContextAccessor();
_
CorporateUserクラスにCorporateUserServiceクラスがあります。サービスクラスは、コンストラクターインジェクションを通じてDbContextを取得します。
次に、CorporateUserServiceを継承する新しいCurrentCorporateUserServiceを作成しました。コンストラクター注入を通じてDbContextおよびIHttpContextAccessorを受け入れます
_public class CurrentCorporateUserService : CorporateUserService
{
private readonly IHttpContextAccessor _httpContextAccessor;
public CurrentCorporateUserService(IHttpContextAccessor httpContextAccessor, MyDbContext context) : base(context)
{
_httpContextAccessor = httpContextAccessor;
}
...
_
基本サービスクラスには、メソッドGetUserByUsername(string username)
があります。現在のサービスクラスは追加のメソッドを追加します
_public CorporateUser GetCurrentUser()
{
return base.GetUserByUsername(_httpContextAccessor.HttpContext.User.Identity.Name.Substring(8));
}
_
現在のサービスクラスはStartup.csに登録されています
_services.AddScoped<CurrentCorporateUserService>();
_
それが済んだら、ディレクティブインジェクションを含むコンポーネントでCurrentCorporateUserServiceを使用できます。
_ [Inject]
private CurrentCorporateUserService CurrentCorporateUserService { get; set; } =
default!;
_
または任意のクラスで、コンストラクターインジェクションを使用します。
_ public MyDbContext( DbContextOptions<MyDbContext> options
, CurrentCorporateUserService CurrentCorporateUserService )
: base(options)
{
_currentUser = CurrentCorporateUserService.GetCurrentUser();
}
_
これをプロジェクト全体のサービスにすることは、すべての開発者が現在のユーザーを取得する方法を気にする必要がなく、サービスをクラスに注入するだけでよいことを意味します。
たとえば、MyDbContextで使用すると、現在のユーザーがすべての保存イベントで使用できるようになります。以下のコードでは、BaseReportクラスを継承するクラスはすべて、レコードが保存されるときにレポートメタデータが自動的に更新されます。
_public override Int32 SaveChanges()
{
var entries = ChangeTracker.Entries().Where(e => e.Entity is BaseReport
&& (e.State == EntityState.Added || e.State == EntityState.Modified));
foreach (var entityEntry in entries)
{
((BaseReport)entityEntry.Entity).ModifiedDate = DateTime.Now;
((BaseReport)entityEntry.Entity).ModifiedByUser = _currentUser.Username;
}
return base.SaveChanges();
}
_
更新-この回答は機能しません。削除するのではなく、情報としてここに示します。代わりに、質問に対する他の回答を検討してください。
services.AddHttpContextAccessor();
を追加します_ [Inject]
private IHttpContextAccessor HttpContextAccessor { get; set; } = default!;
private string username = default!;
_
protected override void OnInitialized()
_ username = HttpContextAccessor.HttpContext.User.Identity.Name;
_
username
は、他の変数と同じようにコンポーネント全体で使用できるようになりました。
ただし、この質問の他の回答を参照して、任意のクラスで使用できるサービスから現在のユーザー名を取得してください。
これは私が動くターゲットを追いかけるのにつらい旅でした。私の場合、Razorページで使用されるBlazorコンポーネントのユーザー名のみが必要でした。私の解決策は以下を必要としました:
Index.cshtml.csに2つのプロパティとコンストラクタを追加しました
public IHttpContextAccessor HttpContextAccessor { get; set; }
public string UserName { get; set; }
public TestModel(IHttpContextAccessor httpContextAccessor)
{
HttpContextAccessor = httpContextAccessor;
if (HttpContextAccessor != null) UserName = HttpContextAccessor.HttpContext.User.Identity.Name;
}
次に、Index.cshtmlで、次のように呼び出したコンポーネントを追加します。
<component type="typeof(MyApp.Components.FileMain)" param-UserName="Model.UserName" render-mode="ServerPrerendered" />
私のコンポーネントでは、コードビハインドファイル(パブリッククラスFileMainBase:ComponentBaseを使用するFileMain.razor.cs)を使用しています。コードは次のとおりです。
[Parameter]
public string UserName { get; set; } = default!;
そして、概念実証としてFileMain.razorページに追加しました
<div class="form-group-sm">
<label class="control-label">User: </label>
@if (UserName != null)
{
<span>@UserName</span>
}
</div>
参考までに、同様の要件があり、以下を使用しています。
var authstate = await AuthenticationsStateProvider.GetAuthenticationStateAsync();
var user = authstate.User;
var name = user.Identity.Name;
私はすでに、startup.csにAuthenticationsStateProviderがあり、それをカスタムクラスのコンストラクターに追加しました。