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

问题描述 投票:0回答:4

我正在使用带有 CookieAuthentication 的 ASP.NET Core MVC。有没有办法可以一次性注销所有用户?我尝试重置 IIS - 没有成功。我尝试删除所有用户的会话(我正在使用数据库进行会话存储) - 没有成功。

有什么想法吗?

asp.net asp.net-core asp.net-core-mvc
4个回答
4
投票

您可以使用

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);
    }
}

3
投票

使用 CookieAuthentication,cookie 只是一个包含用户名、角色和辅助数据的加密字符串。简而言之,它标识的是用户,而不是会话。终止会话不会使 cookie 失效。

话虽这么说,您可以在 cookie 的辅助数据中填充会话标识符或其他令牌,然后在身份验证过程中对其进行验证。可以在here找到有人尝试这样做的示例。

另一个选项是您可以暂时禁用用户存储库中的用户,而不是使会话失效。 这里是使用 ASPNET Identity 2.0 的示例。

第三个(核)选项是更改所有 Web 服务器上的 机器密钥,这将使任何旧表单身份验证 cookie 不可读,迫使所有用户重新登录。


0
投票

这是应用程序需要对后端用户访问更改做出反应的情况。身份验证 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
放入
ConfigureSerices
类中的
Startup
方法内。调用
context.RejectPrincipal()
会立即生效,并将用户踢回登录以获取新的身份验证 cookie。

ConfigureServices
类中的
Startup
方法内注册事件。

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);
        }
    }
}

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

登录

确保在负责登录控制器的操作方法中添加声明。

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 Core Identity 的情况下使用 cookie 身份验证


-2
投票

非常简单。 更改登录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);
            });
© www.soinside.com 2019 - 2024. All rights reserved.