[ Entity Frameworkコア] JJT 2を試してみてください
23414 ワード
イントロ
今回は、最後のプロジェクトの詳細を見ます.
JWTについて
JWT(JSONウェブトークン)は3つのJSON値から作られます.
{Header}.{Payload}.{Signature}
値はbase 64エンコードされます.例えば、“ヘッダー”はトークンタイプ名とアルゴリズム名を持ちます.
(署名は暗号化のために直接デコードできません)
ユーザトークンcs
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
namespace BookshelfSample.Users;
public class UserTokens: IUserTokens
{
...
public string GenerateToken(ApplicationUser user)
{
return new JwtSecurityTokenHandler()
.WriteToken(new JwtSecurityToken(this.config["Jwt:Issuer"],
this.config["Jwt:Audience"],
claims: new []
{
new Claim(ClaimTypes.Email, user.Email)
},
expires: DateTime.Now.AddSeconds(30),
signingCredentials: new SigningCredentials(
new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this.config["Jwt:Key"])),
SecurityAlgorithms.HmacSha256)));
}
public IEnumerable<string> DecodeToken(string value)
{
foreach(var t in value.Split("."))
{
yield return Base64UrlEncoder.Decode(t);
}
}
}
ApplicationUserService。cs
...
public async Task<UserActionResult> SigninAsync(SigninValue value, ISession session)
{
var target = await this.users.GetByEmailForSigninAsync(value.Email);
if(target == null)
{
return ActionResultFactory.GetFailed("Invalid e-mail or password");
}
var result = await this.signInManager.PasswordSignInAsync(target, value.Password, false, false);
if(result.Succeeded)
{
var token = this.userTokens.GenerateToken(target);
session.SetString("user-token", token);
logger.LogDebug($"Token: {token}");
foreach(var t in this.userTokens.DecodeToken(token))
{
logger.LogDebug($"Decoded: {t}");
}
return ActionResultFactory.GetSucceeded();
}
return ActionResultFactory.GetFailed("Invalid e-mail or password");
}
...
結果
Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9lbWFpbGFkZHJlc3MiOiJleGFtcGxlQG1haWwuY29tIiwiZXhwIjoxNjQ4MzEzMDY0LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjUxMTAiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjUxMTAifQ.AtzZ-RnSNG3SRLEsNEC3XI7OjiQ8Y8YWpRdBCTI5vNY
Decoded: {"alg":"HS256","typ":"JWT"}
Decoded: {"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress":"[email protected]","exp":1648397836,"iss":"http://localhost:5110","aud":"http://localhost:5110"}
Decoded: ♀?▼?Q? ←|?☻?L????YGn?Y~?$?1???
の仕様を読むことができますHeader and Claims RFC 7519で.認証
JWTのベアラ認証のために、私はAuthenticationBuilderにオプションを“addjwtearer”を追加しました.
プログラム。cs
...
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])),
};
});
...
“validate ~”プロパティ“false”の全てを設定すると、常に同じトークン値を使用できますか?答えはイエスです.
プログラム。cs
...
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateTokenReplay = false,
ValidateActor = false,
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = false,
ValidateIssuerSigningKey = false,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])),
};
});
...
app.Use(async (context, next) =>
{
var token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9lbWFpbGFkZHJlc3MiOiJleGFtcGxlQG1haWwuY29tIiwiZXhwIjoxNjQ4MzEzMDY0LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjUxMTAiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjUxMTAifQ.AtzZ-RnSNG3SRLEsNEC3XI7OjiQ8Y8YWpRdBCTI5vNY";
context.Request.Headers.Add("Authorization", $"Bearer {token}");
await next();
});
...
セットトークンはセキュリティキーで暗号化されているので、“issuersigningkey”を省略できません.書き込みトークン
次にJWTの作成を見ます.
ユーザトークンcs
...
public string GenerateToken(ApplicationUser user)
{
return new JwtSecurityTokenHandler()
.WriteToken(new JwtSecurityToken(this.config["Jwt:Issuer"],
this.config["Jwt:Audience"],
claims: new []
{
new Claim(ClaimTypes.Email, user.Email)
},
expires: DateTime.Now.AddSeconds(30),
signingCredentials: new SigningCredentials(
new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this.config["Jwt:Key"])),
SecurityAlgorithms.HmacSha256)));
}
...
JwtSecurityTokenには5オーバーロードがあります.しかし、JWTheader、JWtPayload、およびJwtSecurityTokenを引数として受け取りません.jwtSecurityToken.csは、JwtSecurityTokenコンストラクターの他の引数からSigningCredentialsとJWtPayloadからJWTheaderを作成します.
ヘッダとペイロードセクションはbase 64エンコードされたJSONです.
しかし、署名セクションはいくつかのBase 64符号化された値から作られます.
だから私は直接デコードすることはできません.
セキュリティキー
セキュリティキーには特別な要件はありません.
しかし、HMAC SHA 256を使用するので、キー値は少なくとも16ビット長を持たなければなりません.
キーが16ビット未満であるならば、私は実行時例外を得ます.
The encryption algorithm 'System.String' requires a key size of at least 'System.Int32' bits. Key 'Microsoft.IdentityModel.Tokens.SymmetricSecurityKey', is of size: 'System.Int32'. (Parameter 'key')
...
私はアルファベットや数字に加えて、シンボル、日本語などを使用することができます.キーが長か短いかどうか、結果は256ビット長です.
資源
Reference
この問題について([ Entity Frameworkコア] JJT 2を試してみてください), 我々は、より多くの情報をここで見つけました https://dev.to/masanori_msl/aspnet-coreentity-framework-core-try-jwt-2-2iijテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol