在 [.NET 6] 中,将认证信息存储在Redis中,并在注销时将其作废
最近我一直在研究认证周边,并且以柴犬桑的文章为基础,在.NET 6上试用。
确保在ASP.NET Core应用程序注销时有效地使身份验证cookie无效。
我想要做的事情 (Wǒ zuò de
- 
- 認証情報を redis に保持する
 
- ログアウト時に redis の値を削除し認証情報を無効にする
环境 – 一种选择
- 
- Visual Studio 2022 / .NET 6
 
- redis on docker
模块组成
Sample.csproj
└ Controllers
  └ AccountController.cs
  └ ValuesController.cs
└ RedisSessionStore.cs
└ Program.cs
一种选择:代码
        public IActionResult Login()
        {
            var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new[]
            {
                new Claim(ClaimTypes.Name, "test taro"),
                new Claim(ClaimTypes.Role, "Administrator")
            }, CookieAuthenticationDefaults.AuthenticationScheme));
            var authenticationProperties = new AuthenticationProperties
            {
                IsPersistent = true,
                RedirectUri = Url.Action("Index", "Home")
            };
            return SignIn(claimsPrincipal, authenticationProperties, CookieAuthenticationDefaults.AuthenticationScheme);
        }
        public IActionResult Logout()
        {
            var authenticationProperties = new AuthenticationProperties
            {
                RedirectUri = Url.Action("Index", "Home")
            };
            return SignOut(authenticationProperties, CookieAuthenticationDefaults.AuthenticationScheme);
        }
- 
- 単純なログイン/ログアウト処理を定義
 
- 認証情報の取り扱いを確認したいので、固定の Claim を使用する
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        [HttpGet]
        public ActionResult Get() => Ok(new { name = User?.Identity?.Name });
    }
- こちらも、単純に認証情報を取得するだけの処理を定義
    public class RedisSessionStore : ITicketStore
    {
        private readonly IDistributedCache redisCache;
        public RedisSessionStore(IDistributedCache redisCache) => this.redisCache = redisCache;
        // 認証情報を保存する
        public async Task<string> StoreAsync(AuthenticationTicket ticket)
        {
            // Guid をキーに認証情報を redis に保存する
            var key = Guid.NewGuid().ToString();
            await RenewAsync(key, ticket);
            return key;
        }
        // 認証情報を更新する
        public async Task RenewAsync(string key, AuthenticationTicket ticket)
        {
            // 有効期限を 5 分にして保存する
            var serializedTicket = TicketSerializer.Default.Serialize(ticket);
            await redisCache.SetAsync(key, serializedTicket, new DistributedCacheEntryOptions() { SlidingExpiration = TimeSpan.FromMinutes(5) });
        }
        // 認証情報を取得する
        public async Task<AuthenticationTicket?> RetrieveAsync(string key)
        {
            // キーに該当する認証情報を取得。なければ null を返す
            var serializedTicket = await redisCache.GetAsync(key);
            return serializedTicket != null ? TicketSerializer.Default.Deserialize(serializedTicket) : null;
        }
        // 認証情報を削除する
        public async Task RemoveAsync(string key) => await redisCache.RemoveAsync(key);
    }
- ITicketStore を実装し、各メソッドで redis の操作を行う
builder.Services.AddSingleton<IDistributedCache, RedisCache>();
builder.Services.AddSingleton<ITicketStore, RedisSessionStore>();
builder.Services.AddStackExchangeRedisCache(options =>
{
    // docker で起動した redis を指定する
    options.Configuration = "127.0.0.1:6379";
});
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        // こちらも有効期限を 5 分で設定
        options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
    });
builder.Services.AddOptions<CookieAuthenticationOptions>(CookieAuthenticationDefaults.AuthenticationScheme)
    .Configure<ITicketStore>((options, store) => options.SessionStore = store);
- nuget 参照で Microsoft.Extensions.Caching.StackExchangeRedis を追加しておく
Redis.
version: '3'
services:
  redis:
    container_name: redis
    image: redis:latest
    ports:
      - 6379:6379
    volumes:
      - ./data/redis:/data
执行
- 
- /Account/Login にアクセス
 
Cookie の .AspNetCore.Cookies の値をコピー
Postman から /api/values にリクエスト
Key = Cookie / Value = .AspNetCore.Cookies=xxxxxxxxxxxxxxx を設定
“name”: “test taro” がレスポンス
/Account/Logout にアクセス
Postman から /api/values にリクエスト
Key = Cookie / Value = .AspNetCore.Cookies=xxxxxxxxxxxxxxx を設定
“name”: null がレスポンス
 
    