Browse Source

Add `AbpAuthenticationSessionState` to logout from other tabs

pull/19563/head
liangshiwei 2 years ago
parent
commit
8a5762fbb7
  1. 1
      framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalScriptContributor.cs
  2. 8
      framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAuthenticationOptions.cs
  3. 10
      framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ILocalStorageService.cs
  4. 31
      framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/LocalStorageService.cs
  5. 65
      framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpAuthenticationSessionState.cs
  6. 27
      framework/src/Volo.Abp.AspNetCore.Components.Web/wwwroot/libs/abp/js/authentication-session-state-listener.js
  7. 2
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/ComponentsComponentsBundleContributor.cs
  8. 10
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs
  9. 7
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/ClientProxyExceptionEventHandler.cs

1
framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalScriptContributor.cs

@ -15,5 +15,6 @@ public class BlazorGlobalScriptContributor : BundleContributor
context.Files.AddIfNotContains("/_framework/blazor.server.js"); context.Files.AddIfNotContains("/_framework/blazor.server.js");
} }
context.Files.AddIfNotContains("/_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/abp.js"); context.Files.AddIfNotContains("/_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/abp.js");
context.Files.AddIfNotContains("/_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/authentication-session-state-listener.js");
} }
} }

8
framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAuthenticationOptions.cs

@ -0,0 +1,8 @@
namespace Volo.Abp.AspNetCore.Components.Web;
public class AbpAuthenticationOptions
{
public string LoginUrl { get; set; } = "Account/Login";
public string LogoutUrl { get; set; } = "Account/Logout";
}

10
framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ILocalStorageService.cs

@ -0,0 +1,10 @@
using System.Threading.Tasks;
namespace Volo.Abp.AspNetCore.Components.Web;
public interface ILocalStorageService
{
public ValueTask SetItemAsync(string key, string value);
public ValueTask<string> GetItemAsync(string key);
public ValueTask RemoveItemAsync(string key);
}

31
framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/LocalStorageService.cs

@ -0,0 +1,31 @@
using System.Threading.Tasks;
using Microsoft.JSInterop;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.Web;
[Dependency(ReplaceServices = true)]
public class LocalStorageService : ILocalStorageService, ITransientDependency
{
public IJSRuntime JsRuntime { get; }
public LocalStorageService(IJSRuntime jsRuntime)
{
JsRuntime = jsRuntime;
}
public async ValueTask SetItemAsync(string key, string value)
{
await JsRuntime.InvokeVoidAsync("localStorage.setItem", key, value);
}
public async ValueTask<string> GetItemAsync(string key)
{
return await JsRuntime.InvokeAsync<string>("localStorage.getItem", key);
}
public async ValueTask RemoveItemAsync(string key)
{
await JsRuntime.InvokeVoidAsync("localStorage.removeItem", key);
}
}

65
framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpAuthenticationSessionState.cs

@ -0,0 +1,65 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.Extensions.Options;
using Volo.Abp.Users;
namespace Volo.Abp.AspNetCore.Components.Web.Security;
public class AbpAuthenticationSessionState : ComponentBase
{
private const string SessionKey = "authentication-session-id";
[Inject]
protected ILocalStorageService LocalStorage { get; set; } = default!;
[Inject]
protected ICurrentUser CurrentUser { get; set; } = default!;
[Inject]
protected NavigationManager NavigationManager { get; set; } = default!;
[Inject]
protected IOptions<AbpAuthenticationOptions> AuthenticationOptions { get; set; } = default!;
protected async override Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
NavigationManager.RegisterLocationChangingHandler(OnLocationChangingAsync);
if (CurrentUser.IsAuthenticated)
{
await SetAuthenticationStateAsync();
}
else
{
await ClearAuthenticationStateAsync();
}
}
}
protected virtual async ValueTask OnLocationChangingAsync(LocationChangingContext context)
{
if (context.TargetLocation.Contains(AuthenticationOptions.Value.LogoutUrl))
{
await ClearAuthenticationStateAsync();
}
}
protected virtual async Task SetAuthenticationStateAsync()
{
var sessionId = await LocalStorage.GetItemAsync(SessionKey);
if (sessionId.IsNullOrWhiteSpace())
{
sessionId = CurrentUser.FindSessionId() ?? Guid.NewGuid().ToString();
}
await LocalStorage.SetItemAsync(SessionKey, sessionId);
}
protected virtual async Task ClearAuthenticationStateAsync()
{
await LocalStorage.RemoveItemAsync(SessionKey);
}
}

27
framework/src/Volo.Abp.AspNetCore.Components.Web/wwwroot/libs/abp/js/authentication-session-state-listener.js

@ -0,0 +1,27 @@
(function () {
var sessionKey = 'authentication-session-id';
window.addEventListener('storage', function (event) {
console.log(event);
if (event.key !== sessionKey) {
return;
}
var previousSessionId = event.oldValue
var sessionId = event.newValue;
if(previousSessionId === sessionId) {
return;
}
if(previousSessionId || !sessionId) {
abp.utils.removeOidcUser();
window.location.reload();
return;
}
location.assign('/')
});
}());

2
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/ComponentsComponentsBundleContributor.cs

@ -9,6 +9,8 @@ public class ComponentsComponentsBundleContributor : IBundleContributor
context.Add("_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"); context.Add("_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js");
context.Add("_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/abp.js"); context.Add("_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/abp.js");
context.Add("_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/lang-utils.js"); context.Add("_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/lang-utils.js");
context.Add("_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/lang-utils.js");
context.Add("_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/authentication-session-state-listener.js");
} }
public void AddStyles(BundleContext context) public void AddStyles(BundleContext context)

10
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs

@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Volo.Abp.AspNetCore.Components.Server;
using Volo.Abp.AspNetCore.Components.Web; using Volo.Abp.AspNetCore.Components.Web;
using Volo.Abp.AspNetCore.Components.Web.ExceptionHandling; using Volo.Abp.AspNetCore.Components.Web.ExceptionHandling;
using Volo.Abp.AspNetCore.Components.Web.Security; using Volo.Abp.AspNetCore.Components.Web.Security;
@ -49,6 +50,15 @@ public class AbpAspNetCoreComponentsWebAssemblyModule : AbpModule
context.Services context.Services
.GetHostBuilder().Logging .GetHostBuilder().Logging
.AddProvider(new AbpExceptionHandlingLoggerProvider(context.Services)); .AddProvider(new AbpExceptionHandlingLoggerProvider(context.Services));
if (!context.Services.ExecutePreConfiguredActions<AbpAspNetCoreComponentsWebOptions>().IsBlazorWebApp)
{
Configure<AbpAuthenticationOptions>(options =>
{
options.LoginUrl = "authentication/login";
options.LogoutUrl = "authentication/logout";
});
}
} }
public override void PostConfigureServices(ServiceConfigurationContext context) public override void PostConfigureServices(ServiceConfigurationContext context)

7
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/ClientProxyExceptionEventHandler.cs

@ -6,6 +6,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.JSInterop; using Microsoft.JSInterop;
using Volo.Abp.AspNetCore.Components.Server; using Volo.Abp.AspNetCore.Components.Server;
using Volo.Abp.AspNetCore.Components.Web;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus; using Volo.Abp.EventBus;
using Volo.Abp.Http; using Volo.Abp.Http;
@ -28,21 +29,23 @@ public class ClientProxyExceptionEventHandler : ILocalEventHandler<ClientProxyEx
using (var scope = ServiceProvider.CreateScope()) using (var scope = ServiceProvider.CreateScope())
{ {
var options = scope.ServiceProvider.GetRequiredService<IOptions<AbpAspNetCoreComponentsWebOptions>>(); var options = scope.ServiceProvider.GetRequiredService<IOptions<AbpAspNetCoreComponentsWebOptions>>();
if (!options.Value.IsBlazorWebApp) if (!options.Value.IsBlazorWebApp)
{ {
var navigationManager = scope.ServiceProvider.GetRequiredService<NavigationManager>(); var navigationManager = scope.ServiceProvider.GetRequiredService<NavigationManager>();
var accessTokenProvider = scope.ServiceProvider.GetRequiredService<IAccessTokenProvider>(); var accessTokenProvider = scope.ServiceProvider.GetRequiredService<IAccessTokenProvider>();
var authenticationOptions = scope.ServiceProvider.GetRequiredService<IOptions<AbpAuthenticationOptions>>();
var result = await accessTokenProvider.RequestAccessToken(); var result = await accessTokenProvider.RequestAccessToken();
if (result.Status != AccessTokenResultStatus.Success) if (result.Status != AccessTokenResultStatus.Success)
{ {
navigationManager.NavigateToLogout("authentication/logout"); navigationManager.NavigateToLogout(authenticationOptions.Value.LogoutUrl);
return; return;
} }
result.TryGetToken(out var token); result.TryGetToken(out var token);
if (token != null && DateTimeOffset.Now >= token.Expires.AddMinutes(-5)) if (token != null && DateTimeOffset.Now >= token.Expires.AddMinutes(-5))
{ {
navigationManager.NavigateToLogout("authentication/logout"); navigationManager.NavigateToLogout(authenticationOptions.Value.LogoutUrl);
} }
} }
else else

Loading…
Cancel
Save