网站首页 网站源码
website
站点相关全部源代码,隐藏了一些关于服务器的信息
using System.Text;
using Dpz.Core.Auth.Models;
using Dpz.Core.Authenticator;
using Dpz.Core.Service.RepositoryService;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Dpz.Core.Auth.Controllers;

public class TwoFactorController(
    ILogger<HomeController> logger,
    IUserTwoFactorService userTwoFactorService
) : Controller
{
    /// <summary>
    /// 绑定双因素验证
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    [Authorize]
    [Route("two-factor.html")]
    public async Task<IActionResult> BindTwoFactor(string returnUrl = "/")
    {
        var account = User.NameIdentifier;
        if (User.Identity?.IsAuthenticated != true || string.IsNullOrWhiteSpace(account))
        {
            return Challenge(authenticationSchemes: ConstValues.DefaultScheme);
        }
        var (key, isBind) = await userTwoFactorService.GetKeyAsync(account);
        if (isBind)
        {
            return Redirect(returnUrl);
        }

        if (!isBind && string.IsNullOrWhiteSpace(key))
        {
            logger.LogWarning("获取用户密钥失败,账号:{Account}", account);
            return Redirect(returnUrl);
        }

        var twoFactorAuthenticator = new TwoFactorAuthenticator();
        var setupInfo = twoFactorAuthenticator.GenerateSetupCode(
            issuer: "叫我阿胖",
            accountTitleNoSpaces: account,
            accountSecretKey: key,
            secretIsBase32: false
        );
        TempData["FromUrl"] = returnUrl;
        return View(setupInfo);
    }

    [HttpGet]
    [Authorize]
    [Route("unbind-two-factor.html")]
    public async Task<IActionResult> UnBindTwoFactor()
    {
        var account = User.NameIdentifier;
        var (_, isBind) = await userTwoFactorService.GetKeyAsync(account);
        if (!isBind)
        {
            TempData["Msg"] = "您未绑定双因素验证";
        }
        return View();
    }

    [ValidateAntiForgeryToken]
    [Authorize]
    [HttpPost]
    [Route("handel-bind-two-factor")]
    public async Task<IActionResult> HandleBindTwoFactor(string pinCode, string returnUrl = "/")
    {
        var account = User.NameIdentifier;
        if (User.Identity?.IsAuthenticated != true || string.IsNullOrWhiteSpace(account))
        {
            return Challenge(authenticationSchemes: ConstValues.DefaultScheme);
        }

        var (key, isBind) = await userTwoFactorService.GetKeyAsync(account);
        if (isBind)
        {
            return Redirect(returnUrl);
        }
        if (!isBind && string.IsNullOrWhiteSpace(key))
        {
            logger.LogWarning("获取用户密钥失败,账号:{Account}", account);
            return Redirect(returnUrl);
        }

        var twoFactorAuthenticator = new TwoFactorAuthenticator();
        var keyBuffer = Encoding.UTF8.GetBytes(key);
        var keyBase32 = Base32Encoding.ToString(keyBuffer);
        var twoFactorResult = twoFactorAuthenticator.ValidateTwoFactorPIN(keyBase32, pinCode, true);
        if (!twoFactorResult)
        {
            TempData["Msg"] = "PIN码验证失败";
            return RedirectToAction("BindTwoFactor", new { fromUrl = returnUrl });
        }

        await userTwoFactorService.BindAsync(account);
        return Redirect(returnUrl);
    }

    [HttpPost]
    [Authorize]
    [Route("unbind-two-factor")]
    public async Task<IActionResult> HandleUnbindTwoFactor(
        [FromQuery] string returnUrl,
        string pinCode
    )
    {
        var account = User.NameIdentifier;
        if (User.Identity?.IsAuthenticated != true || string.IsNullOrWhiteSpace(account))
        {
            return Challenge(authenticationSchemes: ConstValues.DefaultScheme);
        }
        var (key, isBind) = await userTwoFactorService.GetKeyAsync(account);
        if (!isBind)
        {
            TempData["Msg"] = "您未绑定双因素验证";
            return RedirectToAction("BindTwoFactor", new { returnUrl });
        }

        var twoFactorAuthenticator = new TwoFactorAuthenticator();
        var keyBuffer = Encoding.UTF8.GetBytes(key);
        var keyBase32 = Base32Encoding.ToString(keyBuffer);
        var twoFactorResult = twoFactorAuthenticator.ValidateTwoFactorPIN(keyBase32, pinCode, true);
        if (!twoFactorResult)
        {
            TempData["Msg"] = "PIN码验证失败";
            return RedirectToAction("UnBindTwoFactor", new { returnUrl });
        }

        await userTwoFactorService.UnbindAsync(account);
        return Redirect(returnUrl);
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

上述代码是一个 ASP.NET Core 控制器,名为 TwoFactorController,用于处理用户的双因素身份验证(2FA)相关操作。以下是代码的主要功能和结构的详细解释:

1. 控制器概述

  • 命名空间: Dpz.Core.Auth.Controllers,表明这是一个与身份验证相关的控制器。
  • 依赖注入: 控制器通过构造函数注入了 ILogger<HomeController>IUserTwoFactorService,用于记录日志和处理用户的双因素验证逻辑。

2. 主要功能

控制器提供了以下几个主要功能:

2.1 绑定双因素验证

  • 方法: BindTwoFactor
  • HTTP 方法: GET
  • 路由: /two-factor.html
  • 功能:
    • 检查用户是否已认证。
    • 获取用户的双因素验证密钥。
    • 如果用户已绑定双因素验证,则重定向到指定的返回 URL。
    • 如果未绑定且密钥为空,记录警告并重定向。
    • 生成双因素验证的设置代码,并返回视图以供用户配置。

2.2 解绑双因素验证

  • 方法: UnBindTwoFactor
  • HTTP 方法: GET
  • 路由: /unbind-two-factor.html
  • 功能:
    • 检查用户是否已认证。
    • 获取用户的双因素验证状态。
    • 如果未绑定,设置消息提示用户未绑定双因素验证,并返回视图。

2.3 处理绑定双因素验证

  • 方法: HandleBindTwoFactor
  • HTTP 方法: POST
  • 路由: /handel-bind-two-factor
  • 功能:
    • 检查用户是否已认证。
    • 获取用户的双因素验证密钥。
    • 验证用户输入的 PIN 码。
    • 如果验证成功,绑定双因素验证并重定向到指定的 URL;如果失败,设置错误消息并重定向回绑定页面。

2.4 处理解绑双因素验证

  • 方法: HandleUnbindTwoFactor
  • HTTP 方法: POST
  • 路由: /unbind-two-factor
  • 功能:
    • 检查用户是否已认证。
    • 获取用户的双因素验证状态。
    • 验证用户输入的 PIN 码。
    • 如果验证成功,解绑双因素验证并重定向到指定的 URL;如果失败,设置错误消息并重定向回解绑页面。

3. 其他细节

  • TempData: 用于在重定向后传递消息(如错误提示)。
  • Base32Encoding: 用于将密钥转换为 Base32 格式,以便进行双因素验证。
  • TwoFactorAuthenticator: 这是一个用于生成和验证双因素身份验证 PIN 码的工具类。

总结

这个控制器实现了双因素身份验证的绑定和解绑功能,确保用户在进行敏感操作时能够通过额外的身份验证步骤来提高安全性。通过使用 ASP.NET Core 的身份验证和授权机制,确保只有经过身份验证的用户才能访问这些功能。

loading