You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core网站中为多处「联系我们」表单集成reCaptcha v2

给ASP.NET Core的「联系我们」分部视图添加reCaptcha v2完整方案

既然你已经有了统一的分部视图和视图模型,那给所有页面的表单加上reCaptcha v2就非常高效了,不用逐个页面修改。我给你梳理一套完整的实现步骤:

1. 准备reCaptcha密钥并配置到项目

首先去Google的reCaptcha控制台注册你的网站,获取Site Key(前端用)和Secret Key(后端验证用)。

把密钥存到appsettings.json里,避免硬编码:

"RecaptchaSettings": {
  "SiteKey": "你的Site Key",
  "SecretKey": "你的Secret Key"
}

然后创建一个配置类来映射这些设置:

public class RecaptchaSettings
{
    public string SiteKey { get; set; }
    public string SecretKey { get; set; }
}

在Program.cs里注册这个配置:

builder.Services.Configure<RecaptchaSettings>(builder.Configuration.GetSection("RecaptchaSettings"));

2. 改造视图模型,添加reCaptcha绑定

给你的GetInTouchViewModel加一个属性,用来接收前端的reCaptcha验证token。因为Google的reCaptcha会自动生成一个名为g-recaptcha-response的隐藏字段,我们用BindProperty特性让模型自动绑定这个字段:

public class GetInTouchViewModel
{
    [Required(ErrorMessage = "Please enter your name")]
    public string Name { get; set; }

    // 保留你原有的其他表单属性...

    [Required(ErrorMessage = "Please complete the reCAPTCHA verification")]
    [BindProperty(Name = "g-recaptcha-response")]
    public string RecaptchaToken { get; set; }
}

3. 修改分部视图,添加reCaptcha控件

在你的_GetInTouchSection.cshtml里注入配置,然后添加reCaptcha的控件和脚本:

@model GetInTouchViewModel
@inject IOptions<RecaptchaSettings> RecaptchaSettings

<form asp-action="SubmitGetInTouch" method="post">
    <!-- 保留你原有的表单字段,比如Name输入框等 -->
    <div class="form-group">
        <label asp-for="Name"></label>
        <input asp-for="Name" class="form-control" />
        <span asp-validation-for="Name" class="text-danger"></span>
    </div>

    <!-- 添加reCAPTCHA验证控件 -->
    <div class="form-group mt-3">
        <div class="g-recaptcha" data-sitekey="@RecaptchaSettings.Value.SiteKey"></div>
        <span asp-validation-for="RecaptchaToken" class="text-danger"></span>
    </div>

    <button type="submit" class="btn btn-primary mt-3">Submit</button>
</form>

<!-- 把脚本放到布局的Scripts分部,避免重复加载 -->
@section Scripts {
    <script src="https://www.google.com/recaptcha/api.js" async defer></script>
}

注意:如果你的布局视图里没有@RenderSection("Scripts", required: false),记得加上,一般放在</body>标签前,这样脚本只会加载一次。

4. 实现后端验证服务(关键!)

客户端验证可以被绕过,所以必须在后端验证token的有效性。先创建一个验证服务:

4.1 定义服务接口和实现

public interface IRecaptchaService
{
    Task<bool> VerifyTokenAsync(string token, string remoteIp);
}

public class RecaptchaService : IRecaptchaService
{
    private readonly HttpClient _httpClient;
    private readonly RecaptchaSettings _settings;

    public RecaptchaService(HttpClient httpClient, IOptions<RecaptchaSettings> settings)
    {
        _httpClient = httpClient;
        _settings = settings.Value;
    }

    public async Task<bool> VerifyTokenAsync(string token, string remoteIp)
    {
        var response = await _httpClient.PostAsync(
            "https://www.google.com/recaptcha/api/siteverify",
            new FormUrlEncodedContent(new Dictionary<string, string>
            {
                ["secret"] = _settings.SecretKey,
                ["response"] = token,
                ["remoteip"] = remoteIp
            }));

        if (!response.IsSuccessStatusCode)
            return false;

        var result = await response.Content.ReadFromJsonAsync<RecaptchaVerificationResult>();
        return result.Success;
    }
}

// 用来解析Google返回的验证结果
public class RecaptchaVerificationResult
{
    public bool Success { get; set; }
    public List<string> ErrorCodes { get; set; }
}

4.2 注册服务到DI容器

在Program.cs里添加:

builder.Services.AddHttpClient<IRecaptchaService, RecaptchaService>();

5. 在控制器提交方法里验证reCaptcha

修改处理表单提交的Action,注入IRecaptchaService并验证token:

public class YourController : Controller
{
    private readonly IRecaptchaService _recaptchaService;

    public YourController(IRecaptchaService recaptchaService)
    {
        _recaptchaService = recaptchaService;
    }

    [HttpPost]
    public async Task<IActionResult> SubmitGetInTouch(GetInTouchViewModel model)
    {
        // 获取用户的IP地址,用于reCaptcha验证
        var remoteIp = HttpContext.Connection.RemoteIpAddress?.ToString();
        
        // 验证reCaptcha token
        var isRecaptchaValid = await _recaptchaService.VerifyTokenAsync(model.RecaptchaToken, remoteIp);

        if (!isRecaptchaValid)
        {
            ModelState.AddModelError(nameof(model.RecaptchaToken), "reCAPTCHA verification failed. Please try again.");
        }

        // 检查整个模型的有效性
        if (!ModelState.IsValid)
        {
            // 返回分部视图,保持页面上下文
            return PartialView("_GetInTouchSection", model);
        }

        // 这里处理你的表单提交逻辑,比如发送邮件、保存到数据库等
        // ...

        // 返回成功页面或提示
        return RedirectToAction("ContactSuccess");
    }
}

6. 测试和优化

  • 测试场景:不勾选reCaptcha直接提交,应该会触发客户端提示;勾选后提交,后端会验证token有效性。
  • 错误消息优化:如果需要更具体的错误(比如超时、无效密钥),可以根据RecaptchaVerificationResult里的ErrorCodes来返回对应消息,但一般通用错误就够了。
  • 样式调整:可以给reCaptcha控件加一些CSS类,让它和你的页面风格统一。

内容的提问来源于stack exchange,提问作者Neil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:36:19