Cài đặt thư viện JwtBearer
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
Khai báo thông tin Jwt trong appsettings.json
"Jwt": {
"Issuer": "ceb.net.vn",
"Audience": "ceb.net.vn",
"SecretKey": "23748ijwefkassncmnzcmnjLAKDSJLkuqiowasfdweioruzcasfd01284zxasdfwer",
"Expires": 30
}
Khai báo trong Program.cs
builder.Services.AddAuthentication(p => {
p.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
p.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(p => {
p.TokenValidationParameters = new TokenValidationParameters{
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
ValidateLifetime = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(builder.Configuration["Jwt:SecretKey"] ?? throw new KeyNotFoundException("Jwt:SecretKey")))
};
});
Tạo class LoginResult trả về kết quả đăng nhập
public class LoginResult{
public bool Success { get; set; }
public string? Token { get; set; }
public string Message { get; set; } = null!;
}
Tạo hàm GenerateToken trong class Helper trong Services
public static class Helper{
public static string? GenerateToken(Member obj, IConfiguration configuration){
List<Claim> claims = new List<Claim>{
new Claim(ClaimTypes.NameIdentifier, obj.MemberId!),
new Claim(ClaimTypes.Name, string.IsNullOrEmpty(obj.Surname) ? obj.GivenName : obj.Surname + " " + obj.GivenName),
new Claim(ClaimTypes.Email, obj.Email),
new Claim(ClaimTypes.GivenName, obj.GivenName),
new Claim(ClaimTypes.Role, obj.Role.ToString())
};
if(!string.IsNullOrEmpty(obj.Surname)) claims.Add(new Claim(ClaimTypes.Surname, obj.Surname));
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
SymmetricSecurityKey key = new SymmetricSecurityKey(
Encoding.ASCII.GetBytes(configuration["Jwt:SecretKey"]?? throw new KeyNotFoundException("Jwt:SecretKey"))
);
SigningCredentials credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);
JwtSecurityToken token = new JwtSecurityToken(
issuer: configuration["Jwt:Issuer"],
audience: configuration["Jwt:Audience"],
claims: claims,
expires: DateTime.Now.AddDays(Convert.ToInt32(configuration["Jwt:Expires"])),
signingCredentials: credentials
);
return handler.WriteToken(token);
}
}
Tạo class LoginModel lưu trữ thông tin người dùng nhập vào
public class LoginModel{
public string Email { get; set; } = null!;
public string Password { get; set; } = null!;
}
Kiểm tra đăng nhập
public Member? GetMemberById(string id){
string sql = "SELECT MemberId, GivenName, Surname, Email, Role FROM Member WHERE MemberId = @Id";
return connection.QuerySingleOrDefault<Member>(sql, new {id});
}
public LoginResult Login(LoginModel obj, IConfiguration configuration){
Member? member = GetMemberByEmail(obj.Email);
if(member != null){
if(BCrypt.Net.BCrypt.Verify(obj.Password, member.Password)){
return new LoginResult{
Success = true,
Message = "Login Success",
Token = Helper.GenerateToken(member, configuration)
};
}
return new LoginResult{
Success = false,
Message = "Password invalid",
};
}
return new LoginResult{
Success = false,
Message = "Email invalid"
};
}
Xử lý đăng nhập trả về Jwt Bearer Token
[HttpPost("login")]
public LoginResult Login(LoginModel obj){
return Provider.Member.Login(obj, HttpContext.RequestServices.GetRequiredService<IConfiguration>());
}
Mở file pubspec.yaml khai báo thêm package flutter_secure_storage để lưu trữ thông tin Jwt Token
dependencies:
flutter:
sdk: flutter
http: ^1.6.0
flutter_dotenv: ^6.0.1
flutter_secure_storage: ^11.2.0
class SessionHelper {
static final FlutterSecureStorage storage = FlutterSecureStorage();
static Future<void> save(String token, String email) async {
await storage.write(key: 'token', value: token);
await storage.write(key: 'email', value: email);
}
static Future<String?> get token async {
return await storage.read(key: 'token');
}
static Future<String?> get email async {
return await storage.read(key: 'email');
}
static Future<void> logout() async {
await storage.delete(key: 'token');
await storage.delete(key: 'email');
}
}
static Future<Member?> getProfile(String token) async {
Uri uri = Uri.parse('${dotenv.env['API_URL']}/api/auth');
var response = await http.get(
uri,
headers: {
'content-type': 'application/json',
'Authorization': 'Bearer $token',
},
);
if (response.statusCode == 200) {
return Member.fromMap(jsonDecode(response.body));
}
return null;
}