如何让任何视图知道用户角色(ASP.NET MVC 身份)已更改,以强制任何用户在浏览时注销?

Posted

技术标签:

【中文标题】如何让任何视图知道用户角色(ASP.NET MVC 身份)已更改,以强制任何用户在浏览时注销?【英文标题】:How to make any view aware that the User Roles (ASP.NET MVC Identity) have changed in order to force any user to logout while he or she is browsing? 【发布时间】:2018-03-17 15:21:36 【问题描述】:

我认为问题标题是不言自明的,也许只是当我说“他或她正在浏览”时我在考虑传播或信号时的精确度。

我不希望他或她必须浏览另一个地方只是为了弄清楚 Identity SecurityStamp 已更改并已注销然后重定向到主页,我已经这样做了,但我想知道如果有一个框架(我怀疑很可能是 JS)可以使操作更加“实时”。

[编辑] 可能是 SignalR 的工作,我还没有尝试过。

【问题讨论】:

是的,SignalR 会是更好的选择。 不确定您的负载要求或您想要的“实时”程度,但一个简单的民意调查也可以工作 【参考方案1】:

我设法通过 SignalR 获得了一个可行的解决方案

首先,注意在Startup.Auth.csHow to send message via SignalR to a specific User(Identity Id)? 中设置 SignalR 的顺序,并创建 IUserIdProvider 的实现,该实现仅在 Cookie 和 OwinContext 之后注册,以使其能够利用身份用户字段(即非空)。

public partial class Startup

    public void ConfigureAuth(IAppBuilder appBuilder)
    
        // Order matters here...
        // Otherwise SignalR won't get Identity User information passed to Id Provider...
        ConfigOwinContext(appBuilder);
        ConfigCookies(appBuilder);
        ConfigSignalR(appBuilder);
    

    private static void ConfigOwinContext(IAppBuilder appBuilder)
    
        appBuilder.CreatePerOwinContext(ApplicationDbContext.Create);
        appBuilder.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        appBuilder.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
        appBuilder.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
        appBuilder.CreatePerOwinContext(LdapAdEmailAuthenticator.Create);
    

    private static void ConfigCookies(IAppBuilder appBuilder)
    
        appBuilder.UseCookieAuthentication(new CookieAuthenticationOptions
        
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            Provider = new CookieAuthenticationProvider
            
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>
                (
                    TimeSpan.FromHours(4),
                    (manager, user) => user.GenerateUserIdentityAsync(manager)
                )
            
        );
        appBuilder.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
        appBuilder.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
        appBuilder.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
    

    private static void ConfigSignalR(IAppBuilder appBuilder)
    
        appBuilder.MapSignalR();
        var idProvider = new HubIdentityUserIdProvider();
        GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => idProvider);
    


public class HubIdentityUserIdProvider : IUserIdProvider

    public string GetUserId(IRequest request)
    
        return request == null
            ? throw new ArgumentNullException(nameof(request))
            : request.User?.Identity?.GetUserId();
    

其次,在服务器端声明一个集线器

public class UserHub : Hub


第三,在涉及特定用户注销的更改的控制器(API 或非 API)中,强制注销 + 身份安全标记的更新:

 var userHub = GlobalHost.ConnectionManager.GetHubContext<UserHub>();
 userHub.Clients.User(userId).send("Roles added: " + rolesToAdd.Join() + Environment.NewLine + "Roles removed: " + rolesToRemove.Join());

 return Request.CreateResponse(HttpStatusCode.OK);

第四,在JS客户端使用hub,我创建了一个局部视图,只在当前用户认证时使用,LoggedOutPartialView.cshtml

@if (Request.IsAuthenticated)

    <div class="modal fade" id="loggedOutModal" tabindex="-1" role="dialog" aria-labelledby="loggedOutModalLabel">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h4 class="modal-title" id="loggedOutModalLabel">Notification</h4>
                </div>
                <div class="modal-body">
                    <h6 class="align-center">Sorry, but it seems that you just have been logged out!!!</h6>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                </div>
            </div>
        </div>
    </div>

    <script>

        $(function() 
            var userHub = $.connection.userHub;

            console.log(userHub.client);

            userHub.client.logout= function (message) 
                $('#loggedOutModal').modal('show');
            ;

            $.connection.hub.start().done(function () 
            );
        );

    </script>

【讨论】:

以上是关于如何让任何视图知道用户角色(ASP.NET MVC 身份)已更改,以强制任何用户在浏览时注销?的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core 3.1 MVC 如何让用户在注册时选择自己的角色?

如何在 ASP.NET MVC 中手动设置用户角色?

管理不同的用户角色 ASP.NET MVC [关闭]

如何使用 asp.net mvc 从头开始​​添加用户角色

MVC 3 ASP.NET 角色-授权属性

七天学会ASP.NET MVC ——Layout页面使用和用户角色管理