備忘録

備忘録

ASP.NETでJWTを利用して認証認可する方法

Ⅰ. はじめに

タイトルの通り「ASP.NETでJWTを利用して認証認可する方法」です。

Ⅱ. 環境

  • .NET 7

Ⅲ. 手順

1. 必要なパッケージをインストールする
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer --version 7.0.10
2. 新規Web APIプロジェクトを作成する

Program.cs

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Security.Claims;
using System.Text;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization();

var jwtIssuer = "https://example.com";
var jwtKey = "24f959f5ef4c4126a2996ba618bb46796070307b4837416091c9ed20bbd156a5";

builder.Services
  .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddJwtBearer(options =>
  {
    // HttpContext.Userにマップしない
    options.MapInboundClaims = false;

    options.TokenValidationParameters = new TokenValidationParameters
    {
      ValidIssuer = jwtIssuer,
      ValidAudience = jwtIssuer,
      IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey)),
    };
  });

var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();

// 認証不要
app.MapGet("/test001", (HttpContext context) =>
{
  return "test001";
});

// 認証必須
app.MapGet("/test002", (HttpContext context) =>
{
  var userId = context.User.FindFirstValue("user_id");
  return $"userId: {userId ?? "null"}";
}).RequireAuthorization();

app.Run();
3. 新規コンソールアプリケーションを作成する
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

var jwtIssuer = "https://example.com";
var jwtKey = "24f959f5ef4c4126a2996ba618bb46796070307b4837416091c9ed20bbd156a5";

var claims = new List<Claim>
{
    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString("N")),
    new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss:fff")),
    new Claim("user_id", "1000")
};

var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey));
var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha512);

var token = new JwtSecurityToken(
    jwtIssuer,
    jwtIssuer,
    claims,
    expires: DateTime.Now.AddDays(1),
    signingCredentials: signingCredentials
);

var jwt = new JwtSecurityTokenHandler().WriteToken(token);
Console.WriteLine(jwt);

実行結果

JWT生成結果

eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIwNTFjYzkwNjQ2Yzg0NWFjYWRiYjBjOWFhZjdiNjY2ZiIsImlhdCI6IjIwMjMvMDkvMTEgMTc6MDA6NDE6Mzg1IiwidXNlcl9pZCI6IjEwMDAiLCJleHAiOjE2OTQ1MDU2NDEsImlzcyI6Imh0dHBzOi8vZXhhbXBsZS5jb20iLCJhdWQiOiJodHRwczovL2V4YW1wbGUuY29tIn0.fm3nxVNH-dGV09cvlF_7779o_FhcG9HhArqJWWzHLIcZf531wXi_sfM9F40f27EqOiYZI7Bi1xxIvQEzzMi1rA
# 実行結果
認証不要
認証必須

FAQ

  • Q. algにnoneを指定したJWTを利用した場合は認可されますか?
    A. いいえ。されません。以下エラーが出力されます。
HTTP/1.1 401 Unauthorized
Content-Length: 0
Connection: close
Date: Mon, 11 Sep 2023 07:49:53 GMT
Server: Kestrel
WWW-Authenticate: Bearer error="invalid_token", error_description="The signature key was not found"

TypeScriptで正規表現を利用する方法

Ⅰ. はじめに

タイトルの通り「JavaScriptで正規表現を利用する方法」です。

Ⅱ. サンプルプログラム

const text = `
name:tanaka,age:10
name:yamada,age:20
`

let matches: RegExpExecArray | null = null
const reg = new RegExp('name:([a-z]{1,}),age:([0-9]{1,})', 'g')

while ((matches = reg.exec(text)) !== null) {
  console.log(`name: ${matches[1]}`)
  console.log(`age: ${matches[2]}`)
}

実行結果

name: tanaka
age: 10
name: yamada
age: 20

.NETでランダムに抽出、ランダムに並び替えする方法

Ⅰ. はじめに

タイトルの通り「.NETでランダムに抽出、ランダムに並び替えする方法」です。

Ⅱ. 環境

  • .NET 8以上

Ⅲ. サンプルプログラム

var values = new uint[] { 1, 2, 3, 4 };

// ランダムに3個抽出する。重複有。
var randomValues = Random.Shared.GetItems(values, 3);
Console.WriteLine(string.Join(", ", randomValues));

// 配列をランダムに並び替える。
Random.Shared.Shuffle(values);
Console.WriteLine(string.Join(", ", values));

実行結果

4, 2, 2
2, 4, 1, 3

C#でワンタイムパスワードを生成する方法

Ⅰ. はじめに

タイトルの通り「C#でワンタイムパスワードを生成する方法」です。

Ⅱ. サンプルプログラム

// dotnet add package Otp.NET --version 1.3.0
var totp = new Totp(Base32Encoding.ToBytes("JDDK4U6G3BJLEZ7Y"));
Console.WriteLine(totp.ComputeTotp());

実行結果

ワンタイムパスワードの生成に成功した。Authyの値と一致している。

MariaDBでslow_queryログを出力する方法

Ⅰ. はじめ

タイトルの通り「MariaDBでslow_queryログを出力する方法」です。

Ⅱ. 手順

1. ファイルを編集する

/etc/mysql/mariadb.conf.d/50-server.cnf

[mysqld]
slow_query_log=1 # slow_queryログ出力を有効にする
long_query_time=5 # 5秒以上かかるクエリのログを出力する
#log_queries_not_using_indexes=1 # インデックスが利用されていないクエリログを出力する
slow_query_log_file=/var/log/mysql/slow_query.log # ファイルパス
2. 再起動する
systemctl restart mariadb
3. 設定値を確認する
SHOW GLOBAL VARIABLES like 'slow_query%';

実行結果

/var/log/mysql/slow_query.log

# Time: 230829 17:35:28
# User@Host: user_db[user_db] @  [127.0.0.1]
# Query_time: 5.884430  Lock_time: 0.000016  Rows_sent: 77  Rows_examined: 4841455
SELECT * FROM ...(以下省略)

その他

  • mysqldumpslowを利用するとログファイルのサマリーを出力出来る