如何让任何视图意识到用户角色(ASP.NET MVC标识)已经更改,以强制任何用户在他或她浏览时注销?

时间:2017-10-05 21:42:45

标签: javascript asp.net-mvc signalr asp.net-identity logout

我认为问题标题是不言自明的,当我说"他或她正在浏览时,我可能只是一个精确的标题。我在考虑传播或信号。

我不想让他或她必须浏览另一个地方只是为了弄清楚Identity SecurityStamp已经改变并且已经退出然后被重定向到主页,我已经这样做了但是我我想知道是否有一个框架(我怀疑最有可能是JS)会使操作更多"实时"。

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

1 个答案:

答案 0 :(得分:0)

我设法通过SignalR

获得了可行的解决方案

首先,注意在Startup.Auth.cs How to send message via SignalR to a specific User(Identity Id)?中设置SignalR的顺序,并创建IUserIdProvider的实现,该实现仅在Cookies和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或不包含)中,如果更改涉及注销特定用户,则强制注销+更新身份安全标记:

 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客户端使用集线器,我创建了一个仅在当前用户通过身份验证时使用的局部视图,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>
}