Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/34.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在ASP.net核心标识(UserManager和SignInManager)中,是否可以立即禁止用户?_C#_Asp.net_Asp.net Identity - Fatal编程技术网

C# 在ASP.net核心标识(UserManager和SignInManager)中,是否可以立即禁止用户?

C# 在ASP.net核心标识(UserManager和SignInManager)中,是否可以立即禁止用户?,c#,asp.net,asp.net-identity,C#,Asp.net,Asp.net Identity,我正试图找到一种方法,为我正在开发的应用程序的管理员提供一种有效的方法,以快速锁定已离开公司或已被确定为行为方式可以保证立即锁定或使用该应用程序的用户 到目前为止,看起来我能做到 //enable the account to be locked out _userManager.SetLockoutEnabledAsync(ApplicationUser user, true); //Set an arbitrary date way into the future to lock them

我正试图找到一种方法,为我正在开发的应用程序的管理员提供一种有效的方法,以快速锁定已离开公司或已被确定为行为方式可以保证立即锁定或使用该应用程序的用户

到目前为止,看起来我能做到

//enable the account to be locked out
_userManager.SetLockoutEnabledAsync(ApplicationUser user, true);

//Set an arbitrary date way into the future to lock them out until I want to unlock them
_userManager.SetLockoutEndDateAsync(ApplicationUser user, "01/01/2060");
但上述问题无法解决用户是否拥有过期时间为30分钟的cookie的问题。这意味着,如果用户已经通过身份验证,并且在cookie保持有效的默认时间内,则可以继续使用该应用程序


是否有一个用户管理器方法可以更改cookie所针对的“检查”?我假设[Authorize]属性标记正在对照标识中未在表中公开的内容检查cookie。想知道我如何更改“check”值,使其与cookie会话不匹配吗?

您可以使用一些针对每个请求运行的中间件来实现这一点。首先创建中间件类,如下所示:

public class UserDestroyerMiddleware
{
    private readonly RequestDelegate _next;

    public UserDestroyerMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext httpContext,
        UserManager<ApplicationUser> userManager,
        SignInManager<ApplicationUser> signInManager)
    {
        if (!string.IsNullOrEmpty(httpContext.User.Identity.Name))
        {
            var user = await userManager.FindByNameAsync(httpContext.User.Identity.Name);

            if (user.LockoutEnd > DateTimeOffset.Now)
            {
                //Log the user out and redirect back to homepage
                await signInManager.SignOutAsync();
                httpContext.Response.Redirect("/");
            }
        }
        await _next(httpContext);
    }
}

现在,这个中间件应该在每个请求上运行,检查用户是否应该注销。您可能希望简化此过程,使其不会在每次请求时都命中数据库,而是使用某种缓存的最近删除的用户列表。

多亏了@DavidG的aproach,我对这一点有了更多的思考

在几乎每个控制器中,我都必须获取用户,以确定用户是否属于主机用户组、特定租户用户组,和/或在使用正在更新的对象时,将用户作为编辑器添加到字段(如EditedBy)中

这让我想到的不是

var user = _userManager.GetUserByEmail(User.Identity.Name);

var hostId = user.HostId;

我可以创建一个类来获取用户,但也可以检查用户对象的状态更改,例如“LockoutEnd>Today”或ClaimsHaveBeenUpdated

因此,我提出了一种不同的方法来缓解每个请求上的两个db调用

控制器方法

var user = _userManager.GetUserByEmail(User.Identity.Name);
存储库

public async Task<ApplicationUser> GetUserByEmailAsync(string email)
    {
       var user =  await _context.Users.FirstOrDefaultAsync(x=>x.Email.Equals(email));

        if(user.LockoutEnd > DateTimeOffset.Now )
        {
            await _signInManager.SignOutAsync();
        }
        if (user.CookieStateHasChanged)
        {
            user.CookieStateHasChanged = false;
            await _userManager.UpdateAsync(user);
            await _signInManager.RefreshSignInAsync(user);

        }
        return user;
    }
公共异步任务GetUserByEmailAsync(字符串电子邮件)
{
var user=wait_context.Users.FirstOrDefaultAsync(x=>x.Email.Equals(Email));
如果(user.LockoutEnd>DateTimeOffset.Now)
{
等待_signInManager.SignOutAsync();
}
if(user.cookiestate已更改)
{
user.cookiestatechanged=false;
wait_userManager.UpdateAsync(用户);
等待(u signInManager.RefreshSignInAsync)(用户);;
}
返回用户;
}
不幸的是,在执行其他业务逻辑之前,我已经在每个controller GET方法上为用户调用Db,以确定它是租户还是主机用户。因此,通过将上面的额外代码添加到我的repo中的GetUserByEmailAsync方法中,并将其插入控制器构造函数中,我还可以通过刷新cookie或在用户被锁定时注销用户来处理用户声明更改

请记住,如果角色发生更改,我必须更新user.CookieStateHasChange=true


当用户通过UI被“禁用”时,我会将user.lockouten更新为10年以上。

我认为一个相当简单的方法是为此创建一个过滤器。
可能继承
Authorize
属性并检查当前用户的锁定标志。它也适用于asp.net的早期版本。

Identity framework中没有任何东西可以使这样的用户无效。写一些中间件来实现它应该不会太难。@DavidG谢谢,你知道我可以更新什么吗?这样当遇到[Authorize]时,它的验证值就不同了?很好的解决方案!我只是感到惊讶的是,没有办法改变cookie值所针对的值,从而可以利用正常的授权过程。很高兴知道[authorize]在封面下实际在做什么,但我找不到“实现”之外的任何好文档。cookie保存在用户浏览器中,因此您永远无法更改它。GitHub上提供了类似的代码,当然值得一看。我正在开发一个应用程序,它利用基于Identity 3 cookie的授权、映射到用户的角色以及策略检查声明的角色声明。声明存储在cookie中,其中我的cookie会话默认为30分钟。如果我更改用户角色,则该用户在用户cookie过期或用户注销并重新登录之前,无法访问由策略包装并声明该角色拥有的资源。如果Identity有一个方法来_userManager.LogOutUserAsync(user),那就太好了。通过这种方式,cookie会被重置,声明中的新值为+/-以及锁定。您是否最终使用了此代码(或其变体)?还不知道性能影响是什么。我还在另一篇文章中发布了一个更大的担忧,该文章围绕“x”段时间内的cookie存储声明。希望为所有人找到解决办法。尽管如此,上述解决方案似乎是一个很好的方法。
var tenantId = user.TenantId;
var EditedBy = user.Email;
var user = _userManager.GetUserByEmail(User.Identity.Name);
public async Task<ApplicationUser> GetUserByEmailAsync(string email)
    {
       var user =  await _context.Users.FirstOrDefaultAsync(x=>x.Email.Equals(email));

        if(user.LockoutEnd > DateTimeOffset.Now )
        {
            await _signInManager.SignOutAsync();
        }
        if (user.CookieStateHasChanged)
        {
            user.CookieStateHasChanged = false;
            await _userManager.UpdateAsync(user);
            await _signInManager.RefreshSignInAsync(user);

        }
        return user;
    }