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

无需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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 21:40:57