Bekerja dari jawaban luar biasa Matt Dekrey , saya telah membuat contoh yang sepenuhnya berfungsi untuk otentikasi berbasis token, yang bekerja melawan ASP.NET Core (1.0.1). Anda dapat menemukan kode lengkap dalam repositori ini di GitHub (cabang alternatif untuk 1.0.0-rc1 , beta8 , beta7 ), tetapi secara singkat, langkah-langkah penting adalah:
Buat kunci untuk aplikasi Anda
Dalam contoh saya, saya membuat kunci acak setiap kali aplikasi dimulai, Anda harus membuatnya dan menyimpannya di suatu tempat dan menyediakannya untuk aplikasi Anda. Lihat file ini untuk bagaimana saya membuat kunci acak dan bagaimana Anda dapat mengimpornya dari file .json . Seperti yang disarankan dalam komentar oleh @kspearrin, API Perlindungan Data tampaknya merupakan kandidat yang ideal untuk mengelola kunci "dengan benar", tetapi saya belum berhasil jika itu memungkinkan. Silakan kirim permintaan tarik jika Anda berhasil!
Startup.cs - ConfigureServices
Di sini, kita perlu memuat kunci pribadi agar token kita dapat ditandatangani, yang juga akan kita gunakan untuk memverifikasi token seperti yang disajikan. Kami menyimpan kunci dalam variabel tingkat kelas key
yang akan kami gunakan kembali dalam metode Konfigurasi di bawah ini. TokenAuthOptions adalah kelas sederhana yang memegang identitas penandatangan, pemirsa, dan penerbit yang kita perlukan di TokenController untuk membuat kunci kita.
// 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());
});
Kami juga telah menetapkan kebijakan otorisasi untuk memungkinkan kami menggunakan [Authorize("Bearer")]
pada titik akhir dan kelas yang ingin kami lindungi.
Startup.cs - Konfigurasikan
Di sini, kita perlu mengkonfigurasi 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)
}
});
TokenController
Di pengontrol token, Anda harus memiliki metode untuk menghasilkan kunci yang ditandatangani menggunakan kunci yang dimuat di Startup.cs. Kami telah mendaftarkan instance TokenAuthOptions di Startup, jadi kami harus menyuntikkannya di konstruktor untuk TokenController:
[Route("api/[controller]")]
public class TokenController : Controller
{
private readonly TokenAuthOptions tokenOptions;
public TokenController(TokenAuthOptions tokenOptions)
{
this.tokenOptions = tokenOptions;
}
...
Maka Anda harus membuat token di handler Anda untuk titik akhir login, dalam contoh saya, saya mengambil nama pengguna dan kata sandi dan memvalidasi yang menggunakan pernyataan if, tetapi hal utama yang perlu Anda lakukan adalah membuat atau memuat klaim identitas berbasis dan menghasilkan token untuk itu:
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);
}
Dan seharusnya begitu. Tambahkan saja [Authorize("Bearer")]
ke metode atau kelas apa pun yang ingin Anda lindungi, dan Anda akan mendapatkan kesalahan jika Anda mencoba mengaksesnya tanpa hadiah token. Jika Anda ingin mengembalikan 401 alih-alih kesalahan 500, Anda harus mendaftarkan penangan pengecualian kustom seperti yang saya miliki dalam contoh saya di sini .