我正在使用带有 CookieAuthentication 的 ASP.NET Core MVC。有没有办法可以一次性注销所有用户?我尝试重置 IIS - 没有成功。我尝试删除所有用户的会话(我正在使用数据库进行会话存储) - 没有成功。
有什么想法吗?
您可以使用
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);
}
}
这是应用程序需要对后端用户访问更改做出反应的情况。身份验证 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 身份验证。
非常简单。 更改登录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);
});