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

在WEB API中实现OTP验证的后续请求会话保持

解决Web API中Session无法跨请求获取的问题(OTP验证场景)

我刚碰到过类似的场景,给你梳理下解决思路和具体步骤——核心问题是Web API默认禁用Session,且无状态特性下需要确保请求能正确携带Session凭证,不用数据库完全能搞定:

1. 先在Web API中启用Session支持

Web API默认是无状态设计,所以Session功能是关闭的,需要手动配置开启:

步骤1:配置Startup.cs

在ConfigureServices方法中添加Session服务配置:

services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromMinutes(5); // OTP验证超时设5分钟足够
    options.Cookie.HttpOnly = true; // 防止前端JS读取,提升安全性
    options.Cookie.IsEssential = true; // 标记为必要Cookie,避免用户拒绝非必要Cookie后失效
});

// 跨域配置(如果移动端和API不在同一域名)
services.AddCors(options =>
{
    options.AddPolicy("AllowMobile", policy =>
    {
        policy.WithOrigins("你的移动端域名/IP")
              .AllowAnyHeader()
              .AllowAnyMethod()
              .AllowCredentials(); // 必须开启,允许携带Session Cookie
    });
});

// 添加控制器服务
services.AddControllers();

然后在Configure方法中按正确顺序启用中间件(顺序很重要!):

app.UseRouting();

// 先启用CORS(如果有跨域需求)
app.UseCors("AllowMobile");

// 再启用Session,必须在UseAuthorization和UseEndpoints之前
app.UseSession();

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});

步骤2:给API控制器标记启用Session

Web API控制器默认不支持Session,需要在控制器上添加[SessionState]特性:

[ApiController]
[Route("api/account")]
[SessionState(SessionStateBehavior.Required)] // 告诉框架这个控制器需要Session支持
public class AccountController : ControllerBase
{
    // 你的接口方法
}

Session默认依赖Cookie来标识会话,所以移动端在第一次请求(获取OTP)时,服务器会返回Set-Cookie头,移动端需要保存这个Cookie,后续验证OTP的请求要带上它:

  • 如果是前端框架(比如React Native、Flutter的HTTP库),要开启withCredentials或类似配置(比如Axios的withCredentials: true)
  • 如果是原生iOS/Android,需要手动处理Cookie的存储和在请求中携带

3. 具体代码实现示例

生成并存储OTP的接口

[HttpPost("send-otp")]
public IActionResult SendOtp([FromBody] string targetEmail)
{
    // 生成6位随机OTP
    var otp = new Random().Next(100000, 999999).ToString();
    
    // 把OTP和目标邮箱存入Session
    HttpContext.Session.SetString("EmailUpdateOtp", otp);
    HttpContext.Session.SetString("TargetEmail", targetEmail);
    
    // 这里添加发送OTP到邮箱的逻辑(调用邮件服务等)
    return Ok(new { Message = "OTP已发送至你的邮箱,请在5分钟内验证" });
}

验证OTP并更新邮箱的接口

// 先定义验证模型
public class OtpVerificationRequest
{
    public string Otp { get; set; }
}

[HttpPost("verify-otp")]
public IActionResult VerifyOtp([FromBody] OtpVerificationRequest request)
{
    // 从Session取出存储的OTP和目标邮箱
    var storedOtp = HttpContext.Session.GetString("EmailUpdateOtp");
    var targetEmail = HttpContext.Session.GetString("TargetEmail");
    
    // 检查Session是否有效
    if (storedOtp == null || targetEmail == null)
    {
        return BadRequest(new { Message = "OTP已过期或未生成,请重新获取" });
    }
    
    // 验证OTP
    if (storedOtp.Equals(request.Otp, StringComparison.Ordinal))
    {
        // 这里添加更新用户邮箱的逻辑(比如从当前用户上下文获取用户ID,更新数据库)
        
        // 验证成功后清除Session中的OTP,避免重复使用
        HttpContext.Session.Remove("EmailUpdateOtp");
        HttpContext.Session.Remove("TargetEmail");
        
        return Ok(new { Message = "邮箱更新成功" });
    }
    else
    {
        return BadRequest(new { Message = "无效的OTP,请重新输入" });
    }
}

4. 额外注意点

  • Session安全性:因为Session存在服务器内存中(默认),如果是多服务器部署,需要用分布式Session(比如Redis),单服务器场景完全没问题
  • 超时控制:设置合理的Session超时时间,避免OTP长时间有效
  • 跨域问题:如果移动端和API不在同一域名,必须配置CORS并开启AllowCredentials,否则Cookie无法携带

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:43:50