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
相关产品推荐
相关产品推荐

