私はこのチュートリアルに従いました: https://medium.com/@st.mas29/Microsoft-blazor-web-api-with-jwt-authentication-part-1-f33a44abab9d
例をダウンロードしました: https://github.com/StuwiiDev/DotnetCoreJwtAuthentication/tree/Part2
トークンが作成されていることはわかりますが、SampleDataController
タグが付いているAuthorize
にアクセスするたびに、トークンがクライアント側でどのように保存されるか、または保存される必要があるかがわかりません。 401を返します。
Postmanを使用してトークンを呼び出して追加すると、機能します。
ユーザーを認証するために何が欠けていますか?しないMicrosoft.AspNetCore.Authentication.JwtBearer
クライアント部分を処理します(トークンを保存します)?
これは以前の回答に多少対応しているため、事前にお詫び申し上げますが、コメントする担当者がいません。
BlazorアプリでJWTを使用するための解決策を同様に探していた他の人に役立つ場合は、@ itminusの回答が非常に役立つことがわかりましたが、別のコースも示しました。
私が見つけた問題の1つは、FetchData.cshtml
をもう一度呼び出すと、Authorization
ヘッダーを2回追加しようとすると爆発することでした。
そこにデフォルトのヘッダーを追加する代わりに、ログインが成功した後、HttpClientシングルトンに追加しました(Blazorが自動的に作成すると思います)。したがって、Login.cshtml
のSubmitForm
を@itminusの回答から変更します。
protected async Task SubmitForm()
{
// Remove any existing Authorization headers
Http.DefaultRequestHeaders.Remove("Authorization");
TokenViewModel vm = new TokenViewModel()
{
Email = Email,
Password = Password
};
TokenResponse response = await Http.PostJsonAsync<TokenResponse>("api/Token/Login", vm);
// Now add the token to the Http singleton
Http.DefaultRequestHeaders.Add("Authorization", string.Format("Bearer {0} ", response.Token));
}
次に、SPAを構築しているときよりも、トークンをリクエスト間で永続化する必要がまったくないことに気付きました。トークンはHttpClientにアタッチされているだけです。
次のクラスは、クライアントでのログインプロセスを処理し、JWTトークンをlocal
ストレージに格納します。注:JWTトークンを保存し、サーバーに渡すのは開発者の責任です。クライアント(Blazor、Angularなど)は自動的にそれを行いません。
public class SignInManager
{
// Receive 'http' instance from DI
private readonly HttpClient http;
public SignInManager(HttpClient http)
{
this.http = http;
}
[Inject]
protected LocalStorage localStorage;
public bool IsAuthenticated()
{
var token = localStorage.GetItem<string>("token");
return (token != null);
}
public string getToken()
{
return localStorage.GetItem<string>("token");
}
public void Clear()
{
localStorage.Clear();
}
// model.Email, model.Password, model.RememberMe, lockoutOnFailure: false
public async Task<bool> PasswordSignInAsync(LoginViewModel model)
{
SearchInProgress = true;
NotifyStateChanged();
var result = await http.PostJsonAsync<Object>("/api/Account", model);
if (result)// result.Succeeded
{
_logger.LogInformation("User logged in.");
// Save the JWT token in the LocalStorage
// https://github.com/BlazorExtensions/Storage
await localStorage.SetItem<Object>("token", result);
// Returns true to indicate the user has been logged in and the JWT token
// is saved on the user browser
return true;
}
}
}
//これは、Web APIを呼び出し、現在のユーザーの// JWTトークンを送信する方法です。
public async Task<IList<Profile>> GetProfiles()
{
SearchInProgress = true;
NotifyStateChanged();
var token = signInManager.getToken();
if (token == null) {
throw new ArgumentNullException(nameof(AppState)); //"No token";
}
this.http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
// .set('Content-Type', 'application/json')
// this.http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
Profiles = await this.http.GetJsonAsync<Profile[]>("/api/Profiles");
SearchInProgress = false;
NotifyStateChanged();
}
//クライアントのStartupクラスも次のように設定する必要があります。
public void ConfigureServices(IServiceCollection services)
{
// Add Blazor.Extensions.Storage
// Both SessionStorage and LocalStorage are registered
// https://github.com/BlazorExtensions/Storage
**services.AddStorage();**
...
}
//一般的に言えば、これはクライアントで実行する必要があることです。 //サーバー上に、たとえばアカウントコントローラーにJWTトークンを生成する関数を持つメソッドが必要です。たとえば、JWTミドルウェアを構成して、コントローラーに必要な属性で注釈を付ける必要があります。インスタンス:
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
等々...
お役に立てれば...