ASP.NET Core 8.0 Razor 页面和渐进式 Web 应用程序(添加到移动设备上的主屏幕)无法正常工作(使用 ASP.NET Identity;防伪)

问题描述 投票:0回答:1

我有一个 ASP.NET Core Razor Pages 网页,可以在智能手机(Android 和 iPhone)上浏览。

我使用 ASP.NET Core Identity 来保护对网站的访问。

我的用户希望将图标添加到手机的主屏幕上,以便快速访问该网站(使用移动版本网络浏览器的“将图标添加到主屏幕”功能,该功能显然会“安装”渐进式 Web 应用程序(如果已配置)与清单)。 我无法让它正常工作。 使用主屏幕按钮访问网站时,浏览器似乎不会加载本地网站数据,尤其是 cookie。 如果缺少 ASP.NET Identity Cookie,服务器将重定向到登录页面。 如果我输入凭据并发布表单,服务器会响应

400 Bad Request

日志文件摘录:

2024-12-10 15:00:42.8269|1|INFO|Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.AutoValidateAntiforgeryTokenAuthorizationFilter|Antiforgery token validation failed. The provided antiforgery token was meant for a different claims-based user than the current user. Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The provided antiforgery token was meant for a different claims-based user than the current user.
   at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery.ValidateTokens(HttpContext httpContext, AntiforgeryTokenSet antiforgeryTokenSet)
   at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery.ValidateRequestAsync(HttpContext httpContext)
   at Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.ValidateAntiforgeryTokenAuthorizationFilter.OnAuthorizationAsync(AuthorizationFilterContext context)

防伪令牌的拒绝仅发生在上述上下文中,而不是其他地方。

这个问题我已经困扰很长时间了。我尝试解决该问题的事情:

  1. 向 IIS 服务器添加了签名的 TLS 证书(因为我怀疑浏览器不会对网站使用本地网站数据,因此它不信任)。
  2. 添加了
    manifest.json
    来配置渐进式 Web 应用程序安装。
  3. 添加并使用
    WebEssentials.AspNetCore.PWA

以上都没有帮助我解决这个问题。

清单:

{
  "short_name": "short name",
  "name": "name",
  "start_url": "/",
  "scope": "/",
  "display": "browser",
  "orientation": "portrait",
  "dir": "ltr",
  "lang": "de-DE",
  "theme_color": "#6FC2FF",
  "background_color": "#FFFFFF",
  "icons": [
    {
      "src": "/icons/rageguy512.png",
      "type": "image/png",
      "sizes": "512x512",
      "purpose": "any"
    },
    {
      "src": "/icons/rageguy192.png",
      "type": "image/png",
      "sizes": "192x192",
      "purpose": "any"
    }
  ]
}

我的_Layout.cshtml中的参考:

<link rel="manifest" href="/manifest.json">

程序.cs

using WebEssentials.AspNetCore.Pwa;
// ...
builder.Services.AddProgressiveWebApp(new PwaOptions()
{
     Strategy = ServiceWorkerStrategy.Minimal,
});
// ...

控制器(LoginAsync()),抛出上面提到的400:

using ***.Model.Identity;
using ***.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;



namespace ***.Areas.Identity.Controllers
{
    [Route("[Controller]/[Action]")]
    [Area("Identity")]
    [AutoValidateAntiforgeryToken]
    public class AccountController : Controller
    {
        private readonly SignInManager<ApplicationUser> _signInManager;

        private readonly IUserStore<ApplicationUser> _userStore;

        private readonly UserManager<ApplicationUser> _userManager;

        private readonly ReturnUrlService _returnUrlService;



        public AccountController(SignInManager<ApplicationUser> signInManager,
                                 IUserStore<ApplicationUser> userStore,
                                 UserManager<ApplicationUser> userManager,
                                 ReturnUrlService returnUrlService)
        {
            _signInManager = signInManager;
            _userStore = userStore;
            _userManager = userManager;
            _returnUrlService = returnUrlService;
        }



        [TempData]
        public string? ErrorMessage { get; set; }



        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> LoginAsync([FromForm] LoginInputModel Input)
        {
            if (ModelState.IsValid)
            {
                ApplicationUser? user = await _signInManager.UserManager.FindByIdAsync(Input.Id!);

                if (user == null)
                    return RedirectToPage("/Account/Login");

                var result = await _signInManager.PasswordSignInAsync(user, Input.Password!, true, lockoutOnFailure: true);

                if (result.Succeeded)
                {
                    return LocalRedirect(_returnUrlService.UrlUnescaped());
                }
                if (result.IsLockedOut)
                {
                    return RedirectToPage("/Account/Lockout");
                }
                else
                {
                    TempData.Set("ErrorMessage", "Login-Versuch ungültig!");
                    return RedirectToPage("/Account/Login");
                }
            }

            TempData.Set("ErrorMessage", "Fehler!");
            return RedirectToPage("/Account/Login");
        }



        public class LoginInputModel
        {
            [Required, StringLength(200, ErrorMessage = "Maximal 200 Zeichen.")]
            [Display(Name = "Benutzer")]
            public string? Id { get; set; }

            [Required(ErrorMessage = "Es muss ein Passwort angegeben werden.")]
            [DataType(DataType.Password)]
            [Display(Name = "Passwort")]
            public string? Password { get; set; }
        }



        [HttpPost]
        [Authorize(Policy = "TimeRecordingPolicy")]
        public async Task<IActionResult> LogoutAsync()
        {
            await _signInManager.SignOutAsync();

            return RedirectToPage("/Account/Login");
        }
    }
}

任何帮助表示赞赏。

asp.net-core asp.net-identity progressive-web-apps smartphone antiforgerytoken
1个回答
0
投票

我发现了问题: 显然,在渐进式 Web 应用程序的上下文中,将

samesite-attribute
设置为
strict
的 cookie 处理得不好。我将 ASP.NET Identity Cookie 配置为具有
samesite=lax
,问题就消失了。

Program.cs 摘录:

builder.Services.ConfigureApplicationCookie(o =>
{
    o.LoginPath = "/Identity/Account/Login";
    o.LogoutPath = "/Identity/Account/Logout";
    o.AccessDeniedPath = "/Identity/Account/AccessDenied";
    o.Cookie.MaxAge = TimeSpan.FromDays(6);
    o.Cookie.HttpOnly = true;

    o.Cookie.SameSite = SameSiteMode.Lax; // <=====

    o.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    o.ExpireTimeSpan = TimeSpan.FromDays(6);
    o.SlidingExpiration = true;
});
© www.soinside.com 2019 - 2024. All rights reserved.