۱ سال و ۵ ماه قبل، پنجشنبه ۱۸ اسفند ۱۴۰۱، ساعت ۱۸:۳۳
۱ سال و ۵ ماه قبل، سهشنبه ۱۶ اسفند ۱۴۰۱، ساعت ۱۷:۵۵
این روش برای نوشتن دلیل شکست عملیات در response body، با بازنویسی متد HandleChallengeAsync، آزمایش شده:
using System.Security.Claims; using System.Text; using System.Text.Encodings.Web; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.Extensions.Options; namespace OpenAPISwaggerDoc.Web.Authentication; public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions> { private string _failReason; public BasicAuthenticationHandler( IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { } protected override Task<AuthenticateResult> HandleAuthenticateAsync() { if (!Request.Headers.ContainsKey("Authorization")) { _failReason = "Missing Authorization header"; return Task.FromResult(AuthenticateResult.Fail(_failReason)); } try { var authenticationHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]); var credentialBytes = Convert.FromBase64String(authenticationHeader.Parameter); var credentials = Encoding.UTF8.GetString(credentialBytes).Split(':'); var username = credentials[0]; var password = credentials[1]; if (string.Equals(username, "DNT", StringComparison.Ordinal) && string.Equals(password, "123", StringComparison.Ordinal)) { var claims = new[] { new Claim(ClaimTypes.NameIdentifier, username) }; var identity = new ClaimsIdentity(claims, Scheme.Name); var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, Scheme.Name); return Task.FromResult(AuthenticateResult.Success(ticket)); } _failReason = "Invalid username or password"; return Task.FromResult(AuthenticateResult.Fail(_failReason)); } catch { _failReason = "Invalid Authorization header"; return Task.FromResult(AuthenticateResult.Fail(_failReason)); } } protected override async Task HandleChallengeAsync(AuthenticationProperties properties) { await base.HandleChallengeAsync(properties); if (Response.StatusCode == StatusCodes.Status401Unauthorized && !string.IsNullOrWhiteSpace(_failReason)) { Response.Headers.Add("WWW-Authenticate", _failReason); Response.ContentType = "application/json"; await WriteProblemDetailsAsync(_failReason); } } private Task WriteProblemDetailsAsync(string detail) { var problemDetails = new ProblemDetails { Detail = detail, Status = Context.Response.StatusCode }; var result = new ObjectResult(problemDetails) { ContentTypes = new MediaTypeCollection(), StatusCode = problemDetails.Status, DeclaredType = problemDetails.GetType(), }; var executor = Context.RequestServices.GetRequiredService<IActionResultExecutor<ObjectResult>>(); var routeData = Context.GetRouteData() ?? new RouteData(); var actionContext = new ActionContext(Context, routeData, new ActionDescriptor()); return executor.ExecuteAsync(actionContext, result); } }
۱ سال و ۵ ماه قبل، سهشنبه ۱۶ اسفند ۱۴۰۱، ساعت ۰۲:۰۴
خطای مدنظر را در response body درج کنید:
await Context.Response.WriteAsync("This is why you can't log in");
۱ سال و ۵ ماه قبل، دوشنبه ۱۵ اسفند ۱۴۰۱، ساعت ۱۷:۴۹
یک نکتهی تکمیلی: ساده سازی بازیابی بستههای libman
میشود عملیات libman restore را که توسط وظیفهی DebugEnsureLibManEnv در این مطلب انجام شده، صرفا با افزودن بستهی زیر نیز پیاده سازی و جایگزین کرد:
<PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="2.1.175" />
۱ سال و ۵ ماه قبل، دوشنبه ۱۵ اسفند ۱۴۰۱، ساعت ۱۶:۱۲
یک نکتهی تکمیلی: مشکل تراکنشهای صریح با EnableRetryOnFailure
زمانیکه از EnableRetryOnFailure استفاده میشود، هر کوئری و هر SaveChanges، یک «عملیات قابلتکرار» در صورت شکست خواهد شد (که تعداد بار تکرار آن بستگی به تنظیمات آغازین این متد دارد)؛ البته این در مورد تراکنشهای ضمنی است. اگر در برنامه، یک تراکنش صریح را با فراخوانی BeginTransaction آغاز کنیم، یعنی قصد داریم یک واحد عملیاتی جدید را خودمان به نحو صریحی مشخص کنیم. در این حالت اگر خطایی رخ دهد، نیاز است کل عملیات تراکنش یکبار دیگر تکرار شود و نه اینکه هر کوئری آن یکبار دیگر؛ که در این حالت به استثنای زیر هم خواهیم رسید:
System.InvalidOperationException: The configured execution strategy ‘SqlServerRetryingExecutionStrategy’ does not support user initiated transactions. Use the execution strategy returned by ‘DbContext.Database.CreateExecutionStrategy()’ to execute all the operations in the transaction as a retriable unit.
public async Task<IActionResult> UpdateProduct([FromBody]CatalogItem productToUpdate) { var strategy = _catalogContext.Database.CreateExecutionStrategy(); await strategy.ExecuteAsync(async () => { using (var transaction = _catalogContext.Database.BeginTransaction()) { _catalogContext.CatalogItems.Update(productToUpdate); await _catalogContext.SaveChangesAsync(); transaction.Commit(); } }); }
public class ResilientTransaction { private readonly DbContext _context; private ResilientTransaction(DbContext context) => _context = context ?? throw new ArgumentNullException(nameof(context)); public static ResilientTransaction New(DbContext context) => new(context); public async Task ExecuteAsync(Func<Task> action) { var strategy = _context.Database.CreateExecutionStrategy(); await strategy.ExecuteAsync(async () => { await using var transaction = await _context.Database.BeginTransactionAsync(); await action(); await transaction.CommitAsync(); }); } } // How to use it await ResilientTransaction.New(_dbContext).ExecuteAsync(async () => { // ... await _dbContext.SaveChangesAsync(); });
۱ سال و ۵ ماه قبل، یکشنبه ۱۴ اسفند ۱۴۰۱، ساعت ۱۴:۳۵
- لطفا خارج از موضوع بحث نکنید.
+ از issue tracker پروژه برای این مسایل استفاده کنید. این مورد قبلا مطرح شده. + ^
۱ سال و ۵ ماه قبل، یکشنبه ۱۴ اسفند ۱۴۰۱، ساعت ۱۳:۲۴
با پیاده سازی same-site cookies و همچنین content security policies ، نیازی به نکات بحث جاری ندارید.
به صورت ساده و خلاصه
- بحث anti-forgery token مربوط به برنامههایی هست که از کوکی استفاده میکنند
و نه از JWT. تا زمانیکه JWT را به صورت دستی به هدر درخواست اضافه
میکنید (مانند مثال این سری) و به صورت خودکار از طریق کوکیها ارسال
نمیشود، اساسا CSRF attacks در مورد آنها بیمعنا است.
۱ سال و ۵ ماه قبل، شنبه ۱۳ اسفند ۱۴۰۱، ساعت ۱۱:۵۸
۱ سال و ۵ ماه قبل، شنبه ۱۳ اسفند ۱۴۰۱، ساعت ۰۲:۱۰
۱ سال و ۵ ماه قبل، چهارشنبه ۱۰ اسفند ۱۴۰۱، ساعت ۱۰:۲۴