如何让任何视图意识到用户角色(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?
我认为问题标题是 self-explanatory,当我说 "he or she is browsing" 我考虑的是传播或信号时,可能只是一个精确度。
我不希望他或她不得不浏览另一个地方只是为了弄清楚 Identity SecurityStamp 已更改并已注销然后重定向到主页,我已经这样做了但我我想知道是否有一个框架(我怀疑最有可能是 JS)可以使操作更多 "real-time".
[编辑]
可能是 SignalR 的工作,我还没有尝试过。
我设法通过 SignalR 获得了一个可行的解决方案
首先,注意 SignalR 在 Startup.Auth.cs
中的设置顺序,并创建仅在 Cookies 和 OwinContext 之后注册的 IUserIdProvider 的实现为了使其能够利用身份用户字段(即非空)。
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客户端使用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>
}
我认为问题标题是 self-explanatory,当我说 "he or she is browsing" 我考虑的是传播或信号时,可能只是一个精确度。
我不希望他或她不得不浏览另一个地方只是为了弄清楚 Identity SecurityStamp 已更改并已注销然后重定向到主页,我已经这样做了但我我想知道是否有一个框架(我怀疑最有可能是 JS)可以使操作更多 "real-time".
[编辑]
可能是 SignalR 的工作,我还没有尝试过。
我设法通过 SignalR 获得了一个可行的解决方案
首先,注意 SignalR 在 Startup.Auth.cs
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客户端使用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>
}