如何在ASP.NET Core cookie身份验证中注销所有用户?

lztngnrs  于 12个月前  发布在  .NET
关注(0)|答案(4)|浏览(170)

我使用的是带有CookieAuthentication的ASP.NET Core MVC。是否有方法可以一次性注销所有用户?我尝试重置IIS -不起作用。我尝试删除所有用户的会话(我使用数据库存储会话)-不起作用。
有什么想法吗?

xeufq47z

xeufq47z1#

您可以使用CookieAuthenticationOptions.SessionStore属性,将身份信息存储在服务器端,以便您可以在需要时将其全部清除。

public void ConfigureServices(IServiceCollection services)
{
    MemoryCacheTicketStore memoryCacheTicketStore = new MemoryCacheTicketStore();
    services.AddSingleton<MemoryCacheTicketStore>(memoryCacheTicketStore);

    services.AddAuthentication().AddCookie(cfg =>
    {
        cfg.SessionStore = memoryCacheTicketStore;
    });
}

public class SessionController : Controller
{
    private readonly MemoryCacheTicketStore memoryCacheTicketStore;

    public SessionController(MemoryCacheTicketStore memoryCacheTicketStore)
    {
        this.memoryCacheTicketStore = memoryCacheTicketStore;
    }

    public Task ClearAllSession()
    {
        return memoryCacheTicketStore.ClearAll();
    }
}

public class MemoryCacheTicketStore : ITicketStore
{
    private const string KeyPrefix = "AuthSessionStore-";
    private IMemoryCache _cache;

    public MemoryCacheTicketStore()
    {
        _cache = new MemoryCache(new MemoryCacheOptions());
    }

    public async Task ClearAll()
    {
        _cache.Dispose();
        _cache = new MemoryCache(new MemoryCacheOptions());
    }

    public async Task<string> StoreAsync(AuthenticationTicket ticket)
    {
        var guid = Guid.NewGuid();
        var key = KeyPrefix + guid.ToString();
        await RenewAsync(key, ticket);
        return key;
    }

    public Task RenewAsync(string key, AuthenticationTicket ticket)
    {
        var options = new MemoryCacheEntryOptions();
        var expiresUtc = ticket.Properties.ExpiresUtc;
        if (expiresUtc.HasValue)
        {
            options.SetAbsoluteExpiration(expiresUtc.Value);
        }
        options.SetSlidingExpiration(TimeSpan.FromHours(1)); // TODO: configurable.

        _cache.Set(key, ticket, options);

        return Task.FromResult(0);
    }

    public Task<AuthenticationTicket> RetrieveAsync(string key)
    {
        AuthenticationTicket ticket;
        _cache.TryGetValue(key, out ticket);
        return Task.FromResult(ticket);
    }

    public Task RemoveAsync(string key)
    {
        _cache.Remove(key);
        return Task.FromResult(0);
    }
}

字符串

63lcw9qa

63lcw9qa2#

使用CookieAuthentication,cookie只是一个加密的字符串,包含用户的名称,角色和辅助数据。简而言之,它识别 * 用户 ,而不是 * 会话。 终止会话不会使cookie无效。
也就是说,你可以在cookie的辅助数据中填充一个会话标识符或其他令牌,然后在认证过程中进行验证。
另一种选择是暂时禁用用户存储库中的用户,而不是使会话无效。Here是使用ASPNET Identity 2.0的一个示例。
第三个(核心)选项是更改所有Web服务器上的machine key,这将使任何旧的表单身份验证cookie不可读,迫使所有用户重新登录。

e7arh2l6

e7arh2l63#

在这种情况下,应用程序需要对后端用户访问更改做出React。身份验证Cookie将保护应用程序,但在Cookie的生命周期内保持有效。使用有效Cookie,最终用户在注销或Cookie过期之前不会看到任何更改。
在ASP.NET Core中,验证身份验证cookie更改的最合适的解决方案是通过Cookie身份验证事件。验证事件将从cookie中的标识声明执行后端查找。此事件扩展CookieAuthenticationEvents。这里我们重写ValidatePrincipal方法。

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.Caching.Memory;
using System.Security.Claims;

public class RevokeAuthenticationEvents : CookieAuthenticationEvents
{
    private readonly IMemoryCache _cache;
    private readonly ILogger _logger;

    public RevokeAuthenticationEvents(IMemoryCache cache, ILogger<RevokeAuthenticationEvents> logger)
    {
        _cache = cache;
        _logger = logger;
    }

    public override Task ValidatePrincipal(CookieValidatePrincipalContext context)
    {
        var userId = context.Principal.Claims.First(c => c.Type == ClaimTypes.NameIdentifier).Value;

        if (_cache.Get<bool>("revoke-" + userId))
        {
            context.RejectPrincipal();

            _cache.Remove("revoke-" + userId);
            _logger.LogDebug("{Message}", "Access has been revoked for: " + userId + ".");
        }

        return Task.CompletedTask;
    }
}

字符串
要通过DI设置IMemoryCache,请将AddMemoryCache放在Startup类的ConfigureSerices方法中。调用context.RejectPrincipal()会立即生效,并将用户踢回Login以获取新的身份验证cookie。
Startup类的ConfigureServices方法中注册事件。

options.EventsType = typeof(RevokeAuthenticationEvents);
services.AddScoped<RevokeAuthenticationEvents>();


现在,您可以通过在控制器的相应方法中设置该高速缓存来注销用户:

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using System.Security.Claims;

public class AuthenticationController : Controller
{
    private readonly IUsersService _usersService;
    private readonly IMemoryCache _cache;

    public AuthenticationController(IUsersService usersService, IMemoryCache cache)
    {
        _usersService = usersService;
        _cache = cache;
    }

    [HttpGet]
    public IActionResult Logout()
    {
        // Logout currently logged in user
        var principal = HttpContext.User as ClaimsPrincipal;
        var userId = principal?.Claims.First(c => c.Type == ClaimTypes.NameIdentifier).Value;

        _cache.Set("revoke-" + userId, true);

        return View();
    }

    [HttpGet]
    public async Task LogoutAll()
    {
        // Fetch users from database
        var users = await _usersService.GetAllUsersAsync();

        // Logout all users
        foreach (var user in users)
        {
            var userId = user.Id;
            _cache.Set("revoke-" + userId, true);
        }
    }
}


请注意,这依赖于在控制器操作方法中设置的内存持久性。请记住,这种类型的事件在每个请求中都运行一次,因此您需要使用高效的缓存策略。

登录

确保在Controller中负责登录的action方法中添加声明。

var claims = new List<Claim>
{
    // Set the user id
    new Claim(ClaimTypes.NameIdentifier, userId)
};

var claimsIdentity = new ClaimsIdentity(claims,
    CookieAuthenticationDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties();

await HttpContext.SignInAsync(
    CookieAuthenticationDefaults.AuthenticationScheme,
    new ClaimsPrincipal(claimsIdentity),
    authProperties);


有关更多信息,请参见在没有ASP.NET核心标识的情况下使用cookie身份验证。

iyfamqjs

iyfamqjs4#

这很简单.更改登录cookie名称
在startup.cs中,将默认名称更改为任意名称。

options.Cookie.Name = "NewName";

字符串

完整示例:

services.ConfigureApplicationCookie(options =>
            {
                options.Cookie.Name = "NewName"; //<-- Here
                options.Cookie.HttpOnly = true;
              ...
                options.Events = options.Events ?? new CookieAuthenticationEvents();
                var onForbidden = options.Events.OnRedirectToAccessDenied;
                var onUnauthorized = options.Events.OnRedirectToLogin;
                options.Events.OnRedirectToAccessDenied = (context) => OnRedirect(context, onForbidden, HttpStatusCode.Forbidden);
                options.Events.OnRedirectToLogin = (context) => OnRedirect(context, onUnauthorized, HttpStatusCode.Unauthorized);
            });

相关问题