Hoạt động từ câu trả lời tuyệt vời của Matt Dekrey , tôi đã tạo ra một ví dụ hoạt động đầy đủ về xác thực dựa trên mã thông báo, hoạt động chống lại ASP.NET Core (1.0.1). Bạn có thể tìm thấy mã đầy đủ trong kho lưu trữ này trên GitHub (các nhánh thay thế cho 1.0.0-rc1 , beta8 , beta7 ), nhưng tóm lại, các bước quan trọng là:
Tạo khóa cho ứng dụng của bạn
Trong ví dụ của tôi, tôi tạo một khóa ngẫu nhiên mỗi khi ứng dụng khởi động, bạn sẽ cần tạo một khóa và lưu trữ ở đâu đó và cung cấp cho ứng dụng của bạn. Xem tệp này để biết cách tôi tạo khóa ngẫu nhiên và cách bạn có thể nhập tệp từ tệp .json . Như được đề xuất trong các nhận xét của @kspearrin, API Bảo vệ Dữ liệu có vẻ như là một ứng cử viên lý tưởng để quản lý các khóa "chính xác", nhưng tôi vẫn chưa làm việc nếu điều đó là có thể. Vui lòng gửi yêu cầu kéo nếu bạn giải quyết nó!
Startup.cs - ConfigureService
Tại đây, chúng tôi cần tải một khóa riêng cho các mã thông báo của chúng tôi được ký kết, chúng tôi cũng sẽ sử dụng để xác minh mã thông báo khi chúng được trình bày. Chúng tôi đang lưu trữ khóa trong một biến cấp độ lớp key
mà chúng tôi sẽ sử dụng lại trong phương thức Cấu hình bên dưới. TokenAuthOptions là một lớp đơn giản chứa danh tính, đối tượng và nhà phát hành ký mà chúng ta sẽ cần trong TokenContoder để tạo các khóa của chúng tôi.
// Replace this with some sort of loading from config / file.
RSAParameters keyParams = RSAKeyUtils.GetRandomKey();
// Create the key, and a set of token options to record signing credentials
// using that key, along with the other parameters we will need in the
// token controlller.
key = new RsaSecurityKey(keyParams);
tokenOptions = new TokenAuthOptions()
{
Audience = TokenAudience,
Issuer = TokenIssuer,
SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.Sha256Digest)
};
// Save the token options into an instance so they're accessible to the
// controller.
services.AddSingleton<TokenAuthOptions>(tokenOptions);
// Enable the use of an [Authorize("Bearer")] attribute on methods and
// classes to protect.
services.AddAuthorization(auth =>
{
auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
.RequireAuthenticatedUser().Build());
});
Chúng tôi cũng đã thiết lập một chính sách ủy quyền để cho phép chúng tôi sử dụng [Authorize("Bearer")]
trên các điểm cuối và các lớp mà chúng tôi muốn bảo vệ.
Startup.cs - Cấu hình
Ở đây, chúng ta cần cấu hình JwtBearerAuthentication:
app.UseJwtBearerAuthentication(new JwtBearerOptions {
TokenValidationParameters = new TokenValidationParameters {
IssuerSigningKey = key,
ValidAudience = tokenOptions.Audience,
ValidIssuer = tokenOptions.Issuer,
// When receiving a token, check that it is still valid.
ValidateLifetime = true,
// This defines the maximum allowable clock skew - i.e.
// provides a tolerance on the token expiry time
// when validating the lifetime. As we're creating the tokens
// locally and validating them on the same machines which
// should have synchronised time, this can be set to zero.
// Where external tokens are used, some leeway here could be
// useful.
ClockSkew = TimeSpan.FromMinutes(0)
}
});
Mã thông báo
Trong bộ điều khiển mã thông báo, bạn cần có một phương thức để tạo các khóa đã ký bằng cách sử dụng khóa được tải trong Startup.cs. Chúng tôi đã đăng ký một phiên bản TokenAuthOptions trong Khởi động, vì vậy chúng tôi cần phải thêm nó vào hàm tạo cho TokenContoder:
[Route("api/[controller]")]
public class TokenController : Controller
{
private readonly TokenAuthOptions tokenOptions;
public TokenController(TokenAuthOptions tokenOptions)
{
this.tokenOptions = tokenOptions;
}
...
Sau đó, bạn sẽ cần tạo mã thông báo trong trình xử lý của mình cho điểm cuối đăng nhập, trong ví dụ của tôi, tôi đang lấy tên người dùng và mật khẩu và xác thực những người sử dụng câu lệnh if, nhưng điều quan trọng bạn cần làm là tạo hoặc tải khiếu nại nhận dạng dựa trên và tạo mã thông báo cho điều đó:
public class AuthRequest
{
public string username { get; set; }
public string password { get; set; }
}
/// <summary>
/// Request a new token for a given username/password pair.
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
[HttpPost]
public dynamic Post([FromBody] AuthRequest req)
{
// Obviously, at this point you need to validate the username and password against whatever system you wish.
if ((req.username == "TEST" && req.password == "TEST") || (req.username == "TEST2" && req.password == "TEST"))
{
DateTime? expires = DateTime.UtcNow.AddMinutes(2);
var token = GetToken(req.username, expires);
return new { authenticated = true, entityId = 1, token = token, tokenExpires = expires };
}
return new { authenticated = false };
}
private string GetToken(string user, DateTime? expires)
{
var handler = new JwtSecurityTokenHandler();
// Here, you should create or look up an identity for the user which is being authenticated.
// For now, just creating a simple generic identity.
ClaimsIdentity identity = new ClaimsIdentity(new GenericIdentity(user, "TokenAuth"), new[] { new Claim("EntityID", "1", ClaimValueTypes.Integer) });
var securityToken = handler.CreateToken(new Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor() {
Issuer = tokenOptions.Issuer,
Audience = tokenOptions.Audience,
SigningCredentials = tokenOptions.SigningCredentials,
Subject = identity,
Expires = expires
});
return handler.WriteToken(securityToken);
}
Và đó nên là nó. Chỉ cần thêm [Authorize("Bearer")]
vào bất kỳ phương thức hoặc lớp nào bạn muốn bảo vệ và bạn sẽ gặp lỗi nếu bạn cố truy cập mà không có mã thông báo. Nếu bạn muốn trả về một lỗi thay vì 500, bạn sẽ cần phải đăng ký một trình xử lý ngoại lệ tùy chỉnh như trong ví dụ của tôi ở đây .