【问题标题】:ASP.NET Core Identity email confirmation URL for React routesReact 路由的 ASP.NET Core Identity 电子邮件确认 URL
【发布时间】:2021-04-03 11:29:00
【问题描述】:

我将 React 路由器用于我的 SPA 和 ASP.Net Core 作为 API 后端,使用 Identity 进行身份验证。目前,我正在尝试将电子邮件确认添加为用户注册过程的一部分。困扰我的是如何在不将 URL 路径硬编码到后端的情况下生成确认 URL。

这是我目前正在使用的:

// Somewhere in my UserService.cs...
// '_urlHelper' is an `IUrlHelper` injected into my service
var routeUrl = _urlHelper.RouteUrl("ConfirmEmail_Route",
    new EmailConfirmationRequest { Email = email, Token = token },
    requestScheme);
// Send the URL in some nicely formatted email
await _emailSender.SendConfirmationEmail(email, routeUrl);


// My API controller action to handle email confirmation
[HttpPost(Name = "ConfirmEmail_Route")]
public async Task<ActionResult> ConfirmEmail([FromBody] EmailConfirmationRequest payload)
{
    var response = await _userService.ConfirmEmail(payload.Token, payload.Email);
    ...
}

问题在于,这会生成一个带有类似“/api/auth/ConfirmEmail?Email=...”路径的 URL,但我的 React 路由配置为处理类似“/ConfirmEmail?Email=...”的路径”。这意味着,当打开 URL 时,浏览器显然是直接到达 API 控制器操作,而不是通过我的 SPA(忽略该操作需要 POST 请求的事实)。

这一切都说得通,因为_urlHelper.RouteUrl(...) 只能看到 ASP.Net Core 本身内的控制器操作,而对 React 使用的路由一无所知。我能做的就是像这样对其进行硬编码:

var routeUrl = $"{requestScheme}://{hostname}/ConfirmEmail?Email={email}&Token={token}";

...不是很通用(我需要考虑如何处理端口号、子域等)。

有没有什么好的替代品我还没有找到?


2020 年 12 月 26 日编辑:

我的 SPA 和 API 后端的角色似乎有点混乱。详细地说,这是我在 Startup.cs 中的设置(使用 .Net Core 2.1):

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // Other irrelevant setup left out for brevity
    // ...

    app.UseAuthentication();

    // Setup routing
    // Specific routes are defined in controllers
    app.UseMvc();

    app.MapWhen(ctx => ctx.Request.Path.Value.StartsWith("/api"), builder =>
    {
        builder.UseStatusCodePagesWithReExecute("/api/error/{0}");
    });

    app.MapWhen(ctx => !ctx.Request.Path.Value.StartsWith("/api"), builder =>
    {
        builder.UseStatusCodePagesWithReExecute("/error/{0}");

        builder.UseMvc(routes =>
        {
            // For any path not beginning with "/api" return the SPA (Javascript) bundle
            routes.MapSpaFallbackRoute("spa-fallback", defaults: new { controller = "Home", action = "Index" });
        });
    });
}

换句话说:REST API 应该被视为一个单独的实体,不关心呈现视图,而只公开以 JSON 进行通信的功能。 React SPA 是一个捆绑的 Javascript 文件,它负责所有 UI 渲染以及与 REST API 通信以进行注册、登录等。一切都使用 JWT(令牌)进行身份验证。

这意味着 REST API 不关心 SPA 用于在应用程序中导航用户的路径/URL(至少我希望 API 尽可能不了解客户端/SPA处理 URLs/UI/navigation - 但在这种情况下,如有必要,我可能会例外)。因此,后端中没有与 React 路由 SPA 中使用的路由匹配的控制器操作,这使得_urlHelper.RouteUrl(...) 变得困难,但我愿意接受建议。

【问题讨论】:

  • 在前端为确认页面创建一个页面,当用户单击电子邮件中的链接时,将用户重定向到带有令牌广告查询字符串的前端页面。页面加载时,检查查询字符串并将 HTTP 发布到您的 API
  • @MichaelMao 你的意思是控制器动作“确认页面”吗?在那种情况下,我觉得它违背了 SPA 的目的。如果不是,那么如何生成要放入电子邮件的链接,这样它就不会指向我的 API 端点?
  • 您是否在 SPA 托管登录和其他注册相关页面?
  • 像您的其他 SPA 页面一样生成 URL?
  • @CeemahFour 取决于您所说的“托管”是什么意思。是的,与 UI 相关的所有内容都由 SPA 处理。后端应该是纯 JSON API。因此 JWT 身份验证令牌是由 API 生成的,但 SPA 正在呈现 UI 以供用户输入凭据并基于此获取令牌。

标签: c# reactjs asp.net-core asp.net-core-identity


【解决方案1】:

根据您的评论,“我的 API 后端并不真正了解 SPA 使用的路由”。 我认为您可以要求前端在单击电子邮件中的链接时传递他们想要的 URL。

  1. 用户注册将向后端发出 POST 请求
{
    account: xxx
    confirmEmailUrl: "https://www.example/confirmEmail" 
    // Front-end pass what URL they want and create the corresponding page on their side
    // So they need to create the page by themselves
}
  1. 发送电子邮件
var url = "https://www.example/confirmEmail" + userId
SendEmail(url)

所以当用户收到邮件并点击邮件中的链接时,它会重定向到前端创建的相应页面,您不需要了解前端的任何信息

3.调用前端的confirm API。

They need to implement this by themselves. 
In the confirm page they created when page loaded.
Get userId from query string and call the API you provide

【讨论】:

  • 谢谢,好建议。如果我找不到其他选择,我可能会选择这样的东西。我希望能够通过配置或类似方式而不是客户端输入来处理它,但我想当 SPA 和 API 大部分是分开的时,我可能会要求不可能的事情。
  • 您可以尝试一些方法,为客户提供确认,以便您现在有一个修复 URL。您可以获得推荐 URL,因此您不需要客户端输入 URL 并要求他们在 http://{client domain}/confirmEmail 等修复路径下创建确认页面@
猜你喜欢
  • 2020-11-08
  • 2016-12-11
  • 2021-07-25
  • 1970-01-01
  • 2020-08-16
  • 1970-01-01
  • 2016-03-20
  • 2023-04-04
  • 1970-01-01
相关资源
最近更新 更多