在 [.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 がレスポンス

广告
将在 10 秒后关闭
bannerAds