gpt4 book ai didi

c# - 如何在 .NET Core 6 Web API 中获取 [Authorize] 属性?

转载 作者:行者123 更新时间:2023-12-05 04:28:25 26 4
gpt4 key购买 nike

我是菜鸟,试图在 .NET Core 6 Web API 项目上用 JWT 最简单 可能的方法,但我什至无法让它工作.

要求:您需要登录才能调用GetProductList API。
(我正在项目附带的 Swagger 上对此进行测试)

仅供引用,我的登录 Controller :(按预期工作)

    [HttpPost("login")]
public async Task<ActionResult> Login(LoginDto request)
{
var user = GetUserFromRequest(request);

if (user == null)
return BadRequest("Invalid credentials.");

string jwt = CreateJwtToken(user.Id.ToString());
Response.Cookies.Append(COOKIE_JWT, jwt, _cookieOptions);

return Ok();
}

[HttpGet("user")]
public IActionResult GetUser()
{
try
{
var jwt = Request.Cookies[COOKIE_JWT];
var userId = VerifyJwtAndGetUserId(jwt);

return Ok(GetUserById(userId));
}
catch(Exception ex)
{
return Unauthorized();
}
}

public static string CreateJwtToken(string userId)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JWT_KEY));
var cred = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);
var token = new JwtSecurityToken(
issuer: userId,
expires: DateTime.Now.AddDays(365),
signingCredentials: cred
);
var jwt = new JwtSecurityTokenHandler().WriteToken(token);
return jwt;
}

public static string VerifyJwtAndGetUserId(string jwt)
{
var tokenHandler = new JwtSecurityTokenHandler();
tokenHandler.ValidateToken(jwt, new TokenValidationParameters {
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JWT_KEY)),
ValidateIssuerSigningKey = true,
ValidateIssuer = false,
ValidateAudience = false
}, out SecurityToken validatedToken);

string userId = validatedToken.Issuer;
return userId;
}

问题是,我怎样才能使 [Authorize] 属性起作用?

    [HttpGet("list")]
//[Authorize]
public async Task<ActionResult<List<Product>>> GetProductList()
{
return Ok(GetProducts());
}

上面的方法有效,但是添加 [Authorize] 属性会产生一个带有以下 header 的 401:(虽然上面的 GetUser 没问题)

 content-length: 0 
date: Mon,13 Jun 2022 23:27:32 GMT
server: Kestrel
www-authenticate: Bearer

这是我的 Program.cs 中的内容:(也许这是错误的?)

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => {
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters { // similar to the one in controller
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JWT_KEY)),
ValidateIssuerSigningKey = true,
ValidateIssuer = false,
ValidateAudience = false
};
options.Events = new JwtBearerEvents { // https://spin.atomicobject.com/2020/07/25/net-core-jwt-cookie-authentication/
OnMessageReceived = ctx => {
ctx.Token = ctx.Request.Cookies["jwt"];
return Task.CompletedTask;
}
};
});

解决方案:

app.UseAuthentication(); 移到 app.UserAuthorization(); 之上。

最佳答案

总结

前端

根据 JWT Introduction如下

Whenever the user wants to access a protected route or resource, theuser agent should send the JWT, typically in the Authorization headerusing the Bearer schema. The content of the header should look likethe following:

Authorization: Bearer [token]

所以你需要添加一个header Authorization: Bearer <token>在您对前端的请求中。
前端的一个简单示例。在这个例子中 yourApiUrl应该是你的 list api 路由。

   const token = getCookieValue(`COOKIE_JWT`);
fetch(yourApiUrl, {
headers: {
"Authorization": `Bearer ${token}`,
}
})

getCookieValue 函数

const getCookieValue(name) =>{
document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop() || ''
}

然后您的请求将具有前缀为 [Bearer] 的授权 header 。
来 self 浏览器开发工具的图片。
image

然后是 [Authorize]属性应该有效


后端

可能不是前端的问题,可以检查一下后端的代码。
后端的一些代码示例 .NET 6 WebApi关于生成或检查 JWT token

GenerateToken 函数
用于 Controller 登录时生成token

  public string GenerateToken(TokenModel tokenModel, int 
expireMinutes = 30)
{
var issuer = this._configuration.GetValue<string> ("JwtSettings:Issuer");
var signKey = this._configuration.GetValue<string>
("JwtSettings:SignKey");

// Configuring "Claims" to your JWT Token
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Iss, issuer),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), // JWT ID
new Claim(JwtRegisteredClaimNames.Sub, tokenModel.EmployeeNo), // User.Identity.Name
new Claim(JwtRegisteredClaimNames.NameId, tokenModel.EmployeeNo),
new Claim(JwtRegisteredClaimNames.Name, tokenModel.EmployeeName),
};

for (int i = 0; i < tokenModel.Roles.Length; i++)
{
claims.Add(new Claim("roles", tokenModel.Roles[i]));
}

var userClaimsIdentity = new ClaimsIdentity(claims);

// Create a SymmetricSecurityKey for JWT Token signatures
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(signKey));

// HmacSha256 MUST be larger than 128 bits, so the key can't be too short. At least 16 and more characters.
var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);

// Create SecurityTokenDescriptor
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = userClaimsIdentity,
NotBefore = DateTime.Now, // Default is DateTime.Now
IssuedAt = DateTime.Now, // Default is DateTime.Now
Expires = DateTime.Now.AddMinutes(expireMinutes),
SigningCredentials = signingCredentials
};

// Generate a JWT securityToken, than get the serialized Token result (string)
var tokenHandler = new JwtSecurityTokenHandler();
var securityToken = tokenHandler.CreateToken(tokenDescriptor);
var serializeToken = tokenHandler.WriteToken(securityToken);

return serializeToken;
}

Program.cs
.NET6 WebApiProgram.cs 中的设置关于检查 Jwt token 。
📌 [注意]:方法builder.Services.AddAuthorization(); 必须低于builder.Services.AddAuthentication方法,或将导致错误。

   builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) //check the HTTP Header's Authorization has the JWT Bearer Token
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",

RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role",

// varify Issuer
ValidateIssuer = true,
ValidIssuer = builder.Configuration.GetValue<string>("JwtSettings:Issuer"),

// 📌 Important!!! audience need to be set to false
// Because the default is true.
// So if you didn't set this prop when generate token, then the api will always return a check token error
ValidateAudience = false,

ValidateLifetime = true,

ValidateIssuerSigningKey = true,
IssuerSigningKey =
new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(builder.Configuration.GetValue<string>("JwtSettings:SignKey")))
};
});

builder.Services.AddAuthorization();

VsCode迅雷客户端轻松测试

  1. 使用the thumder client VsCode测试 api 路由。
  2. 使用 swagger 的登录 Controller 获取 JWTToken。
  3. 然后在迅雷客户端粘贴token,并添加前缀Bearer
    迅雷客户端简单图 enter image description here

关于c# - 如何在 .NET Core 6 Web API 中获取 [Authorize] 属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72610112/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com