abpframework / abp

Open-source web application framework for ASP.NET Core! Offers an opinionated architecture to build enterprise software solutions with best practices on top of the .NET. Provides the fundamental infrastructure, cross-cutting-concern implementations, startup templates, application modules, UI themes, tooling and documentation.
https://abp.io
GNU Lesser General Public License v3.0
12.82k stars 3.41k forks source link

Blazor Server Tiered - application configuration cache gets corrupt after refreshing multiple times (race condition) #17836

Open ArneCools opened 12 months ago

ArneCools commented 12 months ago

Is there an existing issue for this?

Description

There seems to be a race-condition with the blazor server cache. When refrshing the page, the previous sessions is still rendered and loaded. Normally that's not an issue I think. But when you have 'translated' strings in your UI, that are rendered after a delay. For example an api-call (or simply using Task.Delay(5000) in OnInitializedAsync. The translation method (@L["LongWelcomeMessage"]) is rendered and called after the slow task has ran. ABP thinks that the cache is too old, so tries to get a new version. Because the blazor session is invalid, the back-end returns a new config with empty roles. That cache is saved. Meanwhile, you are on a new Blazor (signalR) session. After refreshing again, the new (corrupt) cache is used. So the UI thinks you are not authenticated correctly anymore. You stay logged in, but you have no roles & permissions. It only works again after waiting a while and refreshing until the cache is refreshed.

Reproduction Steps

I tested in a fresh project.

  1. Create a new component with the following code:
    
    @page "/MyAuthorizedPage"
    @using MyProject.Localization
    @using Microsoft.Extensions.Localization
    @attribute [Authorize("AbpIdentity.Roles")]
    @inject IStringLocalizer<MyProjectResource> L

@if (_test) {

@L["LongWelcomeMessage"]

}

@code {

private bool _test = false;
protected override async Task OnInitializedAsync()
{
    _test = true;
    await Task.Delay(5000);
}

}



2. Keep refreshing untill it says you are not authorized to view the page. (after cache refresh race-condition)

3. Keep refreshing untill cache is correct again.

### Expected behavior

The roles & permissions should be correct

### Actual behavior

Roles & permissions are gone. 

### Regression?

Only tested in this one

### Known Workarounds

_No response_

### Version

7.4.0

### User Interface

Blazor Server

### Database Provider

EF Core (Default)

### Tiered or separate authentication server

Tiered

### Operation System

Windows (Default)

### Other information

_No response_
maliming commented 11 months ago

hi

Can you upload your test project to GitHub? Thanks

ArneCools commented 11 months ago

https://github.com/ArneCools/abp_blazor_tiered_bug

This is the page you need to go to, to test: https://github.com/ArneCools/abp_blazor_tiered_bug/blob/main/src/MyProject.Blazor/Pages/MyAuthorizedPage.razor

maliming commented 11 months ago

hi

I keep refreshing the page, but unfortunately, I can't reproduce it.

image
ArneCools commented 11 months ago

After refreshing multiple times (using the browser refresh button or ctrl+R) I get this: image

You can also see the administration button is gone.

maliming commented 11 months ago

Yes, I tried many times, but no luck.

ArneCools commented 11 months ago

Very strange. I get this error on my main project too. I even get the bug on our production server.

On production we get this error because there are some slower running api calls. After the call fails ( because of a TaskCanceledException after closing session) the error occurs. I managed to do a workaround by rethrowing the exception if the innerexception is TaskCanceledException. Otherwise de exception is caught, translated strings are 'rendered', and cache gets corrupt.

I'll try to do a screen capture of the steps reproduce as soon as I can

shuangbaojun commented 4 months ago

Is the problem solved?