如何使用从 ajax 调用获取的 JWT 令牌在 MVC 控制器中按角色授权用户



我正在做一个 ASP.NET 核心MVC项目,我放置了一个基本的MVC网站和一个WebApi控制器来处理来自视图的每个调用。

我并没有真正使用整个 MVC 工作流程,只有路由和授权部分,视图是用纯 javascript 和 html 编写的,因此没有来自 MVC ASP.NET 元素,如标签助手或模型。

在第一个索引页面中,我有一个登录表单,它调用(使用 jquery(WebApi 控制器中的操作,在那里我使用 ASP.NET Identity Core 来授权用户,如果用户和密码有效,我返回一个 JWT 令牌。

[Produces("application/json")]
[Route("api/[controller]")]
[AllowAnonymous]
[ApiController]
public class AccountController : ControllerBase
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly ILogger _logger;
private readonly IConfiguration _configuration;
public AccountController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
ILogger<AccountController> logger,
IConfiguration configuration)
{
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
_configuration = configuration;
}
[Route("test")]
[HttpGet]
public async Task<IActionResult> Test()
{
return Ok(await Task.FromResult("Endpoint working"));
}
[Route("login")]
[HttpPost]
public async Task<IActionResult> Login([FromBody] LoginDto model)
{
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, false, false);
if (result.Succeeded)
{
var appUser = _userManager.Users.SingleOrDefault(r => r.Email == model.Email);
return Ok(await GenerateJwtToken(model.Email, appUser));
}
return BadRequest(string.Empty);
}
[Route("logout")]
[HttpGet]
public async Task Logout()
{
await _signInManager.SignOutAsync();
}
private async Task<object> GenerateJwtToken(string email, IdentityUser user)
{
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, email),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(ClaimTypes.NameIdentifier, user.Id)
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JwtKey"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var expires = DateTime.Now.AddDays(Convert.ToDouble(_configuration["JwtExpireDays"]));
var token = new JwtSecurityToken(
_configuration["JwtIssuer"],
_configuration["JwtIssuer"],
claims,
expires: expires,
signingCredentials: creds
);
return await Task.FromResult(new JwtSecurityTokenHandler().WriteToken(token));
}
}

这部分工作正常,在数据库中我有几个具有自己角色的用户。问题是登录后我想将用户重定向到具有受角色保护的操作的 MVC 控制器,控制器如下所示:

public class SecuredController : Controller
{
[Authorize]
public IActionResult Index()
{
return View();
}
[Authorize(Roles = "Role1, Admin")]
public IActionResult Register()
{
return View();
}
[Authorize(Roles = "Role2, Admin")]
public IActionResult Fraud()
{
return View();
}
}

登录后,我正在做类似的事情

window.location = '@Url.Action("Index", "Secured")'

但我总是收到 401 回复。

是否可以将带有令牌的授权标头添加到重定向中?控制器是否会从令牌中理解用户角色?

我将感谢您的指导。

好消息是,您实际上在这里甚至有几个选择。我正在用手机写这篇文章,所以它会非常简洁:

  1. 可以使用ServiceFilterAttribute指定一个CustomJwtAuthorizationFilter,该执行 JWT 的分析、提取声明并具体化要绑定到安全控制器中UserIPrincipal.Identity,如下所示:

    [ServiceFilter(typeof(CustomJwtAuthorizationFilter))]
    public class SecuredController : Controller
    {
    ...
    }
    public class CustomJwtAuthorizationFilter : ActionFilterAttribute
    {
    public override void OnActionExecuting(ActionExecutingContext actionContext)
    {
    // get claims out of JWT in the request's Authorization header
    var claims = ...
    var identity = new ClaimsIdentity(claims);
    actionContext.HttpContext.User = new ClaimsPrincipal(identity);
    ...
    }
    }
    

    这里的诀窍是通过将其ClaimType属性设置为配置的RoleClaimType来确保明确区分表示角色的声明,在大多数情况下,默认情况下应为"role"!!! 😄 。但这几乎应该透明地完成,因为角色声明应该在 JWT 中指定。

  2. 使用一些现有的中间件并Startup.ConfigureServices(IServiceCollection)配置 DI。

相关内容

  • 没有找到相关文章

最新更新