Saya kesulitan dengan cara mengatur otentikasi di layanan web saya. Layanan ini dibangun dengan api web ASP.NET Core.
Semua klien saya (aplikasi WPF) harus menggunakan kredensial yang sama untuk memanggil operasi layanan web.
Setelah beberapa penelitian, saya menemukan otentikasi dasar - mengirim nama pengguna dan kata sandi di header permintaan HTTP. Tetapi setelah berjam-jam penelitian, menurut saya otentikasi dasar bukanlah cara untuk masuk di ASP.NET Core.
Sebagian besar sumber daya yang saya temukan menerapkan otentikasi menggunakan OAuth atau beberapa middleware lainnya. Tapi itu tampaknya terlalu besar untuk skenario saya, serta menggunakan bagian Identitas ASP.NET Core.
Jadi apa cara yang tepat untuk mencapai tujuan saya - otentikasi sederhana dengan nama pengguna dan kata sandi dalam layanan web ASP.NET Core?
Terima kasih sebelumnya!
Sekarang, setelah saya diarahkan ke arah yang benar, inilah solusi lengkap saya:
Ini adalah kelas middleware yang dijalankan pada setiap permintaan yang masuk dan memeriksa apakah permintaan tersebut memiliki kredensial yang benar. Jika tidak ada kredensial atau jika salah, layanan segera merespons dengan kesalahan 401 Tidak Sah .
public class AuthenticationMiddleware { private readonly RequestDelegate _next; public AuthenticationMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { string authHeader = context.Request.Headers["Authorization"]; if (authHeader != null && authHeader.StartsWith("Basic")) { //Extract credentials string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim(); Encoding encoding = Encoding.GetEncoding("iso-8859-1"); string usernamePassword = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword)); int seperatorIndex = usernamePassword.IndexOf(':'); var username = usernamePassword.Substring(0, seperatorIndex); var password = usernamePassword.Substring(seperatorIndex + 1); if(username == "test" && password == "test" ) { await _next.Invoke(context); } else { context.Response.StatusCode = 401; //Unauthorized return; } } else { // no authorization header context.Response.StatusCode = 401; //Unauthorized return; } } }
Ekstensi middleware perlu dipanggil dalam metode Configure dari kelas Startup layanan
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); app.UseMiddleware<AuthenticationMiddleware>(); app.UseMvc(); }
Dan itu saja! :)
Sumber daya yang sangat baik untuk middleware di .Net Core dan otentikasi dapat ditemukan di sini: https://www.exceptionnotfound.net/writing-custom-middleware-in-asp-net-core-1-0/
sumber
Untuk menggunakan ini hanya untuk pengontrol tertentu misalnya gunakan ini:
app.UseWhen(x => (x.Request.Path.StartsWithSegments("/api", StringComparison.OrdinalIgnoreCase)), builder => { builder.UseMiddleware<AuthenticationMiddleware>(); });
sumber
Saya pikir Anda bisa menggunakan JWT (Json Web Tokens).
Pertama, Anda perlu menginstal paket System.IdentityModel.Tokens.Jwt:
$ dotnet add package System.IdentityModel.Tokens.Jwt
Anda perlu menambahkan pengontrol untuk pembuatan token dan otentikasi seperti ini:
public class TokenController : Controller { [Route("/token")] [HttpPost] public IActionResult Create(string username, string password) { if (IsValidUserAndPasswordCombination(username, password)) return new ObjectResult(GenerateToken(username)); return BadRequest(); } private bool IsValidUserAndPasswordCombination(string username, string password) { return !string.IsNullOrEmpty(username) && username == password; } private string GenerateToken(string username) { var claims = new Claim[] { new Claim(ClaimTypes.Name, username), new Claim(JwtRegisteredClaimNames.Nbf, new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString()), new Claim(JwtRegisteredClaimNames.Exp, new DateTimeOffset(DateTime.Now.AddDays(1)).ToUnixTimeSeconds().ToString()), }; var token = new JwtSecurityToken( new JwtHeader(new SigningCredentials( new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Secret Key You Devise")), SecurityAlgorithms.HmacSha256)), new JwtPayload(claims)); return new JwtSecurityTokenHandler().WriteToken(token); } }
Setelah itu perbarui kelas Startup.cs menjadi seperti di bawah ini:
namespace WebAPISecurity { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = "JwtBearer"; options.DefaultChallengeScheme = "JwtBearer"; }) .AddJwtBearer("JwtBearer", jwtBearerOptions => { jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Secret Key You Devise")), ValidateIssuer = false, //ValidIssuer = "The name of the issuer", ValidateAudience = false, //ValidAudience = "The name of the audience", ValidateLifetime = true, //validate the expiration and not before values in the token ClockSkew = TimeSpan.FromMinutes(5) //5 minute tolerance for the expiration date }; }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseAuthentication(); app.UseMvc(); } }
Dan hanya itu, yang tersisa sekarang adalah meletakkan
[Authorize]
atribut pada Pengontrol atau Tindakan yang Anda inginkan.Berikut ini tautan tutorial lurus ke depan lengkap.
http://www.blinkingcaret.com/2017/09/06/secure-web-api-in-asp-net-core/
sumber
Saya telah menerapkan
BasicAuthenticationHandler
untuk otentikasi dasar sehingga Anda dapat menggunakannya dengan atribut standarAuthorize
danAllowAnonymous
.public class BasicAuthenticationHandler : AuthenticationHandler<BasicAuthenticationOptions> { protected override Task<AuthenticateResult> HandleAuthenticateAsync() { var authHeader = (string)this.Request.Headers["Authorization"]; if (!string.IsNullOrEmpty(authHeader) && authHeader.StartsWith("basic", StringComparison.OrdinalIgnoreCase)) { //Extract credentials string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim(); Encoding encoding = Encoding.GetEncoding("iso-8859-1"); string usernamePassword = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword)); int seperatorIndex = usernamePassword.IndexOf(':', StringComparison.OrdinalIgnoreCase); var username = usernamePassword.Substring(0, seperatorIndex); var password = usernamePassword.Substring(seperatorIndex + 1); //you also can use this.Context.Authentication here if (username == "test" && password == "test") { var user = new GenericPrincipal(new GenericIdentity("User"), null); var ticket = new AuthenticationTicket(user, new AuthenticationProperties(), Options.AuthenticationScheme); return Task.FromResult(AuthenticateResult.Success(ticket)); } else { return Task.FromResult(AuthenticateResult.Fail("No valid user.")); } } this.Response.Headers["WWW-Authenticate"]= "Basic realm=\"yourawesomesite.net\""; return Task.FromResult(AuthenticateResult.Fail("No credentials.")); } } public class BasicAuthenticationMiddleware : AuthenticationMiddleware<BasicAuthenticationOptions> { public BasicAuthenticationMiddleware( RequestDelegate next, IOptions<BasicAuthenticationOptions> options, ILoggerFactory loggerFactory, UrlEncoder encoder) : base(next, options, loggerFactory, encoder) { } protected override AuthenticationHandler<BasicAuthenticationOptions> CreateHandler() { return new BasicAuthenticationHandler(); } } public class BasicAuthenticationOptions : AuthenticationOptions { public BasicAuthenticationOptions() { AuthenticationScheme = "Basic"; AutomaticAuthenticate = true; } }
Pendaftaran di Startup.cs -
app.UseMiddleware<BasicAuthenticationMiddleware>();
. Dengan kode ini, Anda dapat membatasi pengontrol apa pun dengan atribut standar Autorize:[Authorize(ActiveAuthenticationSchemes = "Basic")] [Route("api/[controller]")] public class ValuesController : Controller
dan gunakan atribut
AllowAnonymous
jika Anda menerapkan filter otorisasi pada tingkat aplikasi.sumber
Dalam repo Github publik ini https://github.com/boskjoett/BasicAuthWebApi Anda dapat melihat contoh sederhana dari API web ASP.NET Core 2.2 dengan titik akhir yang dilindungi oleh Otentikasi Dasar.
sumber
Seperti yang dikatakan oleh posting sebelumnya, salah satu caranya adalah dengan mengimplementasikan middleware otentikasi dasar kustom. Saya menemukan kode kerja terbaik dengan penjelasan di blog ini: Basic Auth dengan custom middleware
Saya merujuk blog yang sama tetapi harus melakukan 2 adaptasi:
Saat membaca nama pengguna, kata sandi dari file appsettings.json, tambahkan properti hanya baca statis di file Startup. Kemudian baca dari appsettings.json. Terakhir, baca nilai dari mana saja dalam proyek. Contoh:
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public static string UserNameFromAppSettings { get; private set; } public static string PasswordFromAppSettings { get; private set; } //set username and password from appsettings.json UserNameFromAppSettings = Configuration.GetSection("BasicAuth").GetSection("UserName").Value; PasswordFromAppSettings = Configuration.GetSection("BasicAuth").GetSection("Password").Value; }
sumber
Anda bisa menggunakan
ActionFilterAttribute
public class BasicAuthAttribute : ActionFilterAttribute { public string BasicRealm { get; set; } protected NetworkCredential Nc { get; set; } public BasicAuthAttribute(string user,string pass) { this.Nc = new NetworkCredential(user,pass); } public override void OnActionExecuting(ActionExecutingContext filterContext) { var req = filterContext.HttpContext.Request; var auth = req.Headers["Authorization"].ToString(); if (!String.IsNullOrEmpty(auth)) { var cred = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(auth.Substring(6))) .Split(':'); var user = new {Name = cred[0], Pass = cred[1]}; if (user.Name == Nc.UserName && user.Pass == Nc.Password) return; } filterContext.HttpContext.Response.Headers.Add("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", BasicRealm ?? "Ryadel")); filterContext.Result = new UnauthorizedResult(); } }
dan tambahkan atribut ke pengontrol Anda
[BasicAuth("USR", "MyPassword")]
sumber
ASP.NET Core 2.0 dengan Angular
https://fullstackmark.com/post/13/jwt-authentication-with-aspnet-core-2-web-api-angular-5-net-core-identity-and-facebook-login
Pastikan untuk menggunakan jenis filter otentikasi
[Otorisasi (AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
sumber