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

Web Api项目中MVC与Android客户端的Cookie/Token认证适配咨询

当然可以实现!这种混合认证场景超实用

这种同时支持浏览器Cookie认证和移动端Token认证的需求,在实际项目里非常普遍,完全可以通过ASP.NET Identity的扩展配置来实现。下面是具体的实现思路和步骤:

核心思路

ASP.NET Core支持同时配置多种认证方案,我们可以同时启用Cookie认证(给MVC和浏览器Ajax用)和JWT Token认证(给Android客户端用),然后通过授权策略让Web API控制器接受两种认证方式的请求。

具体实现步骤

1. 配置双重认证服务

首先在Startup.cs(或者.NET 6+的Program.cs)里,同时注册Cookie和JWT Bearer两种认证服务:

// 先保留原有的Identity Cookie认证配置
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

// 添加双重认证方案:Cookie + JWT Bearer
services.AddAuthentication()
    // 配置Cookie认证(和MVC共用一套)
    .AddCookie(options =>
    {
        options.LoginPath = "/Account/Login"; // 保持MVC的登录跳转路径
        options.ExpireTimeSpan = TimeSpan.FromHours(2); // 根据需求调整过期时间
    })
    // 配置JWT Token认证
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            // 从配置文件读取密钥、颁发者、受众(可以放在appsettings.json里)
            ValidIssuer = Configuration["Jwt:Issuer"],
            ValidAudience = Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
        };
    });

2. 设置通用授权策略

接下来配置授权策略,让Web API控制器默认接受两种认证方式的请求:

services.AddAuthorization(options =>
{
    options.DefaultPolicy = new AuthorizationPolicyBuilder()
        // 指定允许的两种认证方案
        .AddAuthenticationSchemes(
            CookieAuthenticationDefaults.AuthenticationScheme,
            JwtBearerDefaults.AuthenticationScheme)
        .RequireAuthenticatedUser() // 要求用户必须认证
        .Build();
});

如果你只想让部分Web API控制器支持双重认证,也可以在单个控制器/Action上直接指定:

[Authorize(AuthenticationSchemes = "Cookies,Bearer")]
[ApiController]
[Route("api/[controller]")]
public class MyApiController : ControllerBase
{
    // ...
}

3. 为Android客户端提供Token生成接口

Android客户端需要先获取JWT Token才能请求Web API,所以要写一个匿名可访问的接口来生成Token:

[AllowAnonymous]
[ApiController]
[Route("api/auth")]
public class AuthApiController : ControllerBase
{
    private readonly UserManager<IdentityUser> _userManager;
    private readonly IConfiguration _configuration;

    public AuthApiController(UserManager<IdentityUser> userManager, IConfiguration configuration)
    {
        _userManager = userManager;
        _configuration = configuration;
    }

    [HttpPost("token")]
    public async Task<IActionResult> GenerateToken([FromBody] LoginRequest model)
    {
        // 验证用户账号密码
        var user = await _userManager.FindByNameAsync(model.Username);
        if (user != null && await _userManager.CheckPasswordAsync(user, model.Password))
        {
            // 生成用户声明
            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, user.UserName),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
            };

            // 生成Token
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var token = new JwtSecurityToken(
                issuer: _configuration["Jwt:Issuer"],
                audience: _configuration["Jwt:Audience"],
                claims: claims,
                expires: DateTime.Now.AddHours(1), // Token有效期
                signingCredentials: creds);

            return Ok(new { Token = new JwtSecurityTokenHandler().WriteToken(token) });
        }

        return Unauthorized("账号或密码错误");
    }
}

// 登录请求模型
public class LoginRequest
{
    public string Username { get; set; }
    public string Password { get; set; }
}

4. 处理跨域和Cookie传递(如果需要)

如果你的Web API和MVC前端是跨域的,或者Android客户端是跨域请求,需要配置CORS允许携带凭证:

services.AddCors(options =>
{
    options.AddPolicy("AllowCredentials", policy =>
    {
        policy.WithOrigins("https://your-mvc-domain.com", "https://your-android-app-domain") // 指定允许的域名
              .AllowAnyMethod()
              .AllowAnyHeader()
              .AllowCredentials(); // 关键:允许携带Cookie或Token凭证
    });
});

// 在中间件管道里启用CORS(要放在UseRouting之后,UseAuthorization之前)
app.UseCors("AllowCredentials");

另外,浏览器端的Ajax请求要设置携带凭证:

  • jQuery示例:
$.ajax({
    url: "/api/your-endpoint",
    type: "GET",
    xhrFields: {
        withCredentials: true // 允许携带Cookie
    }
});
  • Fetch示例:
fetch("/api/your-endpoint", {
    credentials: "include"
});

额外注意事项

  • 确保所有需要认证的Web API Action都加上[Authorize]属性,这样才会触发认证逻辑。
  • Token的过期时间和刷新机制可以根据业务需求调整,比如添加刷新Token的接口,避免用户频繁登录。
  • 测试时可以分别用浏览器(带Cookie)和Postman(带Bearer Token)请求同一个Web API接口,验证两种认证方式都能正常工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:32:30