分享程式代碼相關筆記
目前文章總數:157 篇
最後更新:2024年 12月 07日
建立 Asp.Net Core WebAPI 專案,請使用C# 6.0以上版本
在.net core中,會預設配置Swagger(),在Development環境下時會自動啟用
我們預期在Swagger中可以使用 Jwt,所以要在Nuget安裝該套件
選擇JwtBearer安裝即可。
1. 網站建構 | : | 網站程序初始化的入口點,這邊調整Swagger配置,使期可配置JWT |
2. 資源配置 | : | JWT的憑證、發行者、使用者密鑰配置 |
3. WebAPI | : | API的配置內容、範例實現登入、登入後取用戶資訊 |
4. JWT產生器 | : | 產生Json Web Token的方法 |
網站建構主要完成4個部分,如下說明
1. 增加右上角Bearer token | : | 使用Swagger時增加右上角的按鈕 |
2. 建立JwtBearer | : | 我們使用JwtBearer套件,當呼叫API時會自動驗證JWT |
3. 註冊 Json Web Token產生器 | : | 依賴註冊Service |
4. 添加驗證 | : | 讓Attribute的Authorize標題啟用,使API會進行驗證 |
代碼可參考如下:
var builder = WebApplication.CreateBuilder(args);
\\配置其他Service...
// 1. 增加右上角Bearer token
builder.Services.AddSwaggerGen(o =>
{
o.SwaggerDoc("v1", new OpenApiInfo()
{
Title = "JWT Authentication",
Description = "API如果不是[AllowAnonymous] 需要先執行Member/Login 取得JWT Token",
});
o.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
Name = "Authorization",
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header,
Description = "驗證使用方式:Authentication輸入。 格式:[Bearer 您的Token]",
});
o.AddSecurityRequirement(new OpenApiSecurityRequirement() {
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] {}
}});
});
//2-1. 建立JwtBearer
builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
//2-2. 配置:驗證錯誤時是否顯示錯誤資訊
options.IncludeErrorDetails = true;
//2-3. 配置:Swagger的Bearer的自動驗證
options.TokenValidationParameters = new TokenValidationParameters
{
// 2-4. 配置:驗證 Issuer
ValidateIssuer = true,
ValidIssuer = builder.Configuration.GetValue<string>("JwtSettings:Issuer"),
// 2-5. 配置:驗證 Audience
ValidateAudience = false,
ValidAudience = builder.Configuration.GetValue<string>("JwtSettings:Audience"), // 不驗證就不需要填寫
// 2-6. 配置:驗證 Token憑證
ValidateIssuerSigningKey = false,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration.GetValue<string>("JwtSettings:SignKey"))),
// 2-7. 配置:驗證 Token 有效時限
ValidateLifetime = true
};
});
//3. 註冊 Json Web Token產生器
builder.Services.AddScoped<IJsonWebTokenService, JsonWebTokenService>();
var app = builder.Build();
\\配置其他app configure...
//4. 添加驗證,Attribute => [Authorize]
app.UseAuthorization();
app.Run();
添加產生Token所需的相關金鑰,這邊用到使用者、發行者、憑證
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
//1. 添加JWT的相關密鑰
"JwtSettings": {
"Issuer": "JwtLoginIssuer",
"Audience ": "JwtLoginAudience",
"SignKey": "this_is_a_secure_key_with_length_greater_than_32"
},
"AllowedHosts": "*"
}
這邊分成三個部分
1. 實現登入API | : | 添加 [AllowAnonymous] 標頭表示可以任意訪問,如果有輸入帳號密碼取得Token |
2. 使用者訊息API | : | 添加 [Authorize] 會經過驗證JWT,通過後才可以取得內容否則,回傳401(驗證失敗) |
3. 註冊 JwtBearer 套件 | : | 這邊宣告 [Authorize] 會使用 JwtBearerDefaults 的套件,使有掛載的API,都會經過JWT自動驗證 |
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace NetCoreSwaggerJWTExample.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
//3. 這邊Authorize改用 JwtBearer 套件
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class MemberController : ControllerBase
{
private readonly IJsonWebTokenService _jwtService;
public MemberController(IJsonWebTokenService jsonWebToken)
{
_jwtService = jsonWebToken;
}
/// <summary>
/// 1-1. 登入
/// </summary>
[HttpPost]
[AllowAnonymous]
public ActionResult Login(string user, string password)
{
string token = string.Empty;
//1-2. 假設登入成功,回傳Token
if (!string.IsNullOrEmpty(user) && !string.IsNullOrEmpty(password))
{
token = _jwtService.GenerateToken(user);
}
return Ok(token);
}
/// <summary>
/// 2-1. 使用者訊息API
/// </summary>
[HttpGet]
[Authorize]
public ActionResult UserInfo()
{
//2-2. 驗證通過可以取得使用者訊息
return Ok("取得用戶資訊成功");
}
}
}
產生TOKEN的方法,可以參閱
這邊不同的是從 appsettings.json 取得金鑰
public class JsonWebTokenService : IJsonWebTokenService
{
private readonly string _secretKey;
private readonly string _issur;
private readonly string _audience;
public JsonWebTokenService(IConfiguration configuration)
{
_secretKey = configuration.GetValue<string>("JwtSettings:SignKey");
_issur = configuration.GetValue<string>("JwtSettings:Issuer");
_audience = configuration.GetValue<string>("JwtSettings:Audience");
}
//1. 產生Token
public string GenerateToken(string user)
{
var claims = new[] {
new Claim(ClaimTypes.Name, user)
};
var jwtKey = Encoding.UTF8.GetBytes(_secretKey);
var signingCredentials = new SigningCredentials(new SymmetricSecurityKey(jwtKey), SecurityAlgorithms.HmacSha256);
//2-1. Token產生的issuer、audience、signingCredentials 要與JWTBearer 的配置相同
var token = new JwtSecurityToken(
issuer: _issur,
audience: _audience,
signingCredentials: signingCredentials,
claims: claims,
expires: DateTime.UtcNow.AddSeconds(10)
);
//2-2. 轉為String回傳
var newToken = new JwtSecurityTokenHandler().WriteToken(token);
return newToken;
}
}
執行Debug模式,可以看到預設帶到Swagger首頁,有2個API
1. Login
2. UserInfo
先關注到API UserInfo,我們點擊Try it out
執行Execute後,可以看到下面黑框 Response Stauts 401 ,沒有經過驗證
執行Execute後,可以看到下面黑框 Response Stauts 401 ,沒有經過驗證
關注到API Login 進行登入,這邊只是測試,隨意輸入帳號密碼取得Token
成功登入後,將取得的Json Web Token複製,我們要將其貼到Swagger的驗證中,使API可以訪問
1.回到頁面最上方,點擊右上角的Authorize
2.將Token貼上到Value的位置,一定要在前面加上 Bearer 後面有一個空白字元,如下:
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiMTIzIiwiZXhwIjoxNjg4MDAzODM2LCJpc3MiOiJKd3RMb2dpbklzc3VlciJ9.6fmvcTd_gN2kNFA5wknZIx-vXi0lUS3gBM7AhFcUd1Y
執行Authorize,完成
這時再次執行API UserInfo,可以正常訪問了
如果隔一段時間,再次執行API UserInfo,會發現又出現 401,這是正常的,因為我們在JWT中有設定令牌秒數。
※一個合理的JWT時間應視系統而決定,如果太長會有被攻擊的風險,太短則會需頻繁的產生Token
var token = new JwtSecurityToken(
issuer: _issur,
audience: _audience,
signingCredentials: signingCredentials,
claims: claims,
expires: DateTime.UtcNow.AddSeconds(10)//超過10秒就超時
);