无需API控制器,基于JWT实现登录认证与授权方案咨询
不用API控制器实现JWT登录认证与授权
1. 配置JWT服务(Program.cs)
首先在启动类中配置JWT认证基础服务,这是实现JWT验证的核心前提:
var builder = WebApplication.CreateBuilder(args); // 注册JWT认证服务 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])) }; // 如果用Cookie存储令牌,需要配置从Cookie中提取令牌 options.Events = new JwtBearerEvents { OnMessageReceived = context => { context.Token = context.Request.Cookies["JwtToken"]; return Task.CompletedTask; } }; }); // 注册授权服务 builder.Services.AddAuthorization(); // 注册MVC控制器支持 builder.Services.AddControllersWithViews(); var app = builder.Build(); // 启用认证、授权中间件(顺序不能错) app.UseAuthentication(); app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
在appsettings.json中添加JWT配置参数:
{ "Jwt": { "Key": "YourSecureKeyAtLeast16CharactersLong", "Issuer": "YourApplicationName", "Audience": "YourApplicationUsers" } }
2. 创建独立登录控制器(MVC控制器)
创建普通MVC控制器处理登录请求,完成用户验证与JWT令牌生成:
public class AuthController : Controller { private readonly IConfiguration _config; public AuthController(IConfiguration config) { _config = config; } [HttpGet] public IActionResult Login() { return View(); } [HttpPost] public IActionResult Login(LoginViewModel model) { if (!ModelState.IsValid) return View(model); // 替换为实际用户验证逻辑(如数据库查询) bool isValidUser = ValidateCredentials(model.Username, model.Password); if (!isValidUser) { ModelState.AddModelError("", "用户名或密码错误"); return View(model); } // 生成JWT令牌 var token = GenerateJwtToken(model.Username); // 将令牌存入HttpOnly Cookie(安全性更高) Response.Cookies.Append("JwtToken", token, new CookieOptions { HttpOnly = true, Secure = Environment.IsProduction(), SameSite = SameSiteMode.Strict, Expires = DateTime.UtcNow.AddHours(2) }); // 跳转至授权后页面 return RedirectToAction("Index", "Dashboard"); } private bool ValidateCredentials(string username, string password) { // 示例验证逻辑,实际需对接用户数据库 return username == "admin" && password == "yoursecurepassword"; } private string GenerateJwtToken(string username) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"])); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); // 添加自定义声明(可扩展角色、权限等信息) var claims = new List<Claim> { new Claim(ClaimTypes.Name, username), new Claim(ClaimTypes.Role, "Admin") }; var token = new JwtSecurityToken( issuer: _config["Jwt:Issuer"], audience: _config["Jwt:Audience"], claims: claims, expires: DateTime.UtcNow.AddHours(2), signingCredentials: credentials); return new JwtSecurityTokenHandler().WriteToken(token); } [HttpGet] public IActionResult Logout() { // 清除令牌Cookie Response.Cookies.Delete("JwtToken"); return RedirectToAction("Login"); } }
对应的登录视图模型:
public class LoginViewModel { [Required(ErrorMessage = "请输入用户名")] public string Username { get; set; } [Required(ErrorMessage = "请输入密码")] [DataType(DataType.Password)] public string Password { get; set; } }
3. 实现授权验证
在需要权限的控制器或Action上添加[Authorize]属性即可完成授权拦截:
[Authorize] public class DashboardController : Controller { public IActionResult Index() { // 获取当前登录用户信息 var currentUser = User.Identity.Name; var userRoles = User.Claims.Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value); return View(); } }
在视图中可直接判断用户认证状态:
@if (User.Identity.IsAuthenticated) { <div>欢迎, @User.Identity.Name!</div> <a href="/Auth/Logout">退出登录</a> } else { <a href="/Auth/Login">请登录</a> }
关键注意事项
- 生产环境务必使用HTTPS,避免令牌被窃取
- 密钥要足够长且保密,建议通过环境变量注入而非硬编码
- 可扩展令牌声明,添加用户ID、权限等业务所需信息
- 如果是前后端分离场景,也可将令牌以JSON格式返回,由前端存储在
localStorage,请求时通过Authorization: Bearer {token}头携带
内容的提问来源于stack exchange,提问作者Qasim Asghar
相关产品推荐
相关产品推荐

