اشتراک‌ها
بررسی تازه‌های C# 12

What’s new in C# 12 and beyond | BRK203H

#MSBuild
Take a tour of upcoming language features in C#. While still very much in the works, C# 12 is starting to take shape. We touch on some of the longer-term work that the language design team is focused on. 

بررسی تازه‌های C# 12
اشتراک‌ها
انجام SEO بر روی برنامه های Angular

We certainly have many old-fashioned ways to embed full SEO support for Angular JS, but many consider JavaScript SEO as a friendly option. This is because it uses special URL routing and creates headless browser settings to automatically retrieve the HTML. Read on to learn more. 

انجام SEO بر روی برنامه های Angular
اشتراک‌ها
Bootstrap Icons v1.8.0 منتشر شد

Bootstrap Icons v1.8.0 is here with over 140 new icons, including dozens of new heart icons ready for Valentine’s Day and dozens of filetype icons. We’re not at almost 1,700 icons and is once again our second largest release. Keep reading to see what’s new. 

Bootstrap Icons v1.8.0 منتشر شد
اشتراک‌ها
حالت‌های مختلف از دست رفتن کوکی‌ها در مرورگرها

My browser lost its cookies” has long been one of the most longstanding Support complaints in the history of browsers. Unfortunately, the reason that it has been such a longstanding issue is that it’s not the result of a single problem, and if the problem is intermittent (as it often is), troubleshooting the root cause may be non-trivial.  

حالت‌های مختلف از دست رفتن کوکی‌ها در مرورگرها
اشتراک‌ها
کنترل امن استثنائات کنترل نشده در زبان های #C و VB.NET

Unhandled exceptions are a bit of a misnomer. In .NET, every exception is handled. By the time you access the specifics of an error in your Try-Catch block, the Framework has already analyzed the problem, built a structure to contain its details, examined the stack trace, and used reflection to pinpoint the location of the error, among other mundane tasks. In short, when errors occur, .NET serves them up to your code in a neatly packaged, highly examinable data block.

 
کنترل امن استثنائات کنترل نشده در زبان های #C و VB.NET
مطالب
Garbage Collector در #C - قسمت سوم
در قسمت قبلی درباره تفاوت‌های Stack و Heap، صحبت کرده و به این نتیجه رسیدیم که برای آزادسازی حافظه Heap، در صورتی‌که نخواهیم اینکار را بصورت دستی انجام دهیم، نیاز به Garbage Collector پیدا خواهیم کرد.


تاریخچه‌ای مختصر از GC در NET.

ایده اولیه ایجاد Garbage Collector در NET.، در سال 1990 بود که در آن زمان، مایکروسافت مشغول پیاده سازی خود از JavaScript بنام JScript بود. در ابتدا JScript توسط تیمی چهار نفره توسعه داده میشد و در آن زمان یکی از اعضای این تیم به نام Patrick Dussud که بعنوان پدر Garbage Collector در NET. شناخته میشود، یک Conservative GC را داخل تیم توسعه داد. در آن زمان CLR ای وجود نداشت و Patrick Dussud برروی JVM کار میکرد.

مایکروسافت سعی بر پیاده سازی نسخه‌ای اختصاصی از JVM را برای خود بجای ایجاد چیزی شبیه به NET Runtime. فعلی داشت؛ اما بعد از شکل گیری تیم CLR، به این نتیجه رسیدند که JVM برای آنها محدودیت‌هایی را ایجاد میکند و به همین دلیل شروع به ایجاد Environment خود کردند.

با این تصمیم، Patrick Dussud مجددا یک GC جدید را با ایده "بهترین GC ممکن" با زبان LISP که در آن بیشترین مهارت را داشت، بصورت Prototype نوشت و سپس یک Transpiler از LISP را به ++C نوشت که کدهای آن قابل استفاده در Runtime مایکروسافت باشد.

کدهای فعلی مربوط به Garbage Collector مورد استفاده در NET. در این فایل از ریپازیتوری runtime مایکروسافت قابل دسترسی هستند. در حال حاضر خانم Maoni Stephens مدیر فنی تیم GC مایکروسافت هستند که کنفرانس‌ها و مقالات زیادی نیز درباره نکات مختلف پیاده سازی GC در بلاگ خود نوشته و ارائه کرده‌اند.


در حال حاضر، سه حالت (flavor) از GC در NET. تعبیه شده‌است و هرکدام از این حالات برای انواع مختلفی از برنامه‌ها بهینه شده‌است که در ادامه به بررسی آنها میپردازیم.


Server GC

این نوع GC برای برنامه‌های سمت سرور نظیر ASP.NET Core و WCF بهینه سازی شده‌است که تعداد ریکوئست‌های زیادی به آنها وارد میشود و هر ریکوئست باعث allocate شدن اشیا مختلفی شده و بطور کلی، نرخ allocation و deallocation در آنها بالاست.

Server GC به ازای هر پردازنده، از یک Heap و یک GC Thread مجزا استفاده میکند. این بدین معناست که اگر شما یک پردازنده را با هشت Core داشته باشید، در زمان Garbage Collection، روی هرکدام از Coreها یک Heap و GC Thread مستقل وجود دارد که عمل Garbage Collection را انجام میدهند.

این شکل عملکرد باعث میشود که Collection، در سریعترین زمان ممکن، بدون وقفه اضافه انجام شود و برنامه شما اصطلاحا ((Freeze)) نشود.

Server GC فقط روی پردازنده‌های چند هسته‌ای قابل اجراست و اگر سعی کنید برنامه خود را روی یک سیستم با پردازنده تک هسته‌ای در حالت Server GC اجرا کنید، بصورت خودکار برنامه شما از Non-Concurrent Workstation GC استفاده کرده و اصطلاحا Fallback خواهد شد.

اگر نیاز دارید که در برنامه‌هایی به‌غیر از Server-Side Applicationها، نظیر WPF و Windows Service‌ها و ... از این نوع GC استفاده کنید (به شرط چند هسته بودن پردازنده)، میتوانید این تنظیمات را به فایل app.config یا web.config خود اضافه کنید:
<configuration>
  <runtime>
    <gcServer enabled="true"/>
  </runtime>
</configuration>

همچنین در برنامه‌های NET Core.ای نیز میتوانید این تنظیمات را داخل فایل csproj. برنامه خود اضافه کنید:
<PropertyGroup>
  <ServerGarbageCollection>true</ServerGarbageCollection>
</PropertyGroup>


Concurrent Workstation GC


این حالت، حالت پیشفرض مورد استفاده در برنامه‌های Windows Forms و Windows Service است. این حالت از GC برای برنامه‌هایی بهینه شده‌است که در آنها، هنگام وقوع Garbage Collection، برنامه توقف و مکث حتی چند لحظه‌ای نداشته و Collection باعث نشود که کاربر نتواند روی یک دکمه کلیک کند و اصطلاحا برنامه ((Unresponsive)) شود.

برای فعالسازی Concurrent Workstation GC این تنظیمات را داخل config برنامه خود باید اعمال کنید:
<configuration>
  <runtime>
    <gcConcurrent enabled="true" />
  </runtime>
</configuration>


Non-Concurrent Workstation GC


این حالت شبیه به حالت Server GC است؛ با این تفاوت که عمل Collection روی Thread ای که درخواست allocate کردن یک object را کرده است، صورت میگیرد.

برای مثال:

  • Thread شماره یک درخواست allocate کردن یک string با طول 10000 کاراکتر را میدهد.
  • حافظه، فضای کافی برای تخصیص این حجم از حافظه را نداشته و سعی میکند با اجرای Garbage Collector، این حجم فضای مورد نیاز از حافظه را خالی کند.
  • CLR تمام Thread‌های برنامه را متوقف میکند و Garbage Collector شروع به کار کرده و اشیا بلااستفاده «روی Thread ای که آن را فراخوانی کرده است» را Collect میکند.
  • بعد از پایان Collection، تمامی Threadهای برنامه که در مرحله قبل متوقف شده بودند، مجددا شروع به کار خواهند کرد.


این حالت از GC برای برنامه‌های Server-Side ای که برروی پردازنده تک هسته‌ای اجرا میشوند، پیشنهاد میشود. برای فعالسازی این حالت، تنظیمات داخل config برنامه به این صورت باید تغییر پیدا کند:
<configuration>
  <runtime>
    <gcConcurrent enabled="false" />
  </runtime>
</configuration>



این جدول، کمک خواهد کرد که بر اساس نوع برنامه خود، تنظیمات درستی را برای GC اعمال نمایید (در اکثر موارد، تنظیمات پیشفرض بهترین انتخاب بوده و نیازی به تغییر روند کار GC نیست):

 Server GC  Non-Concurrent Workstation  Concurrent Workstation  
 Maximize throughput on multi-processor machines for server apps that create multiple threads to handle the same types of requests.  Maximize throughput on single-processor machines.  Balance throughput and responsiveness for client apps with UI. Design Goal 
1 per processor ( hyper thread aware )  1  Number of Heaps
 1 dedicated GC thread per processor The thread which performs the allocation that triggers the GC. The thread which performs the allocation that triggers the GC.  GC Threads
 EE is suspended during a GC. EE is suspended during a GC. EE is suspended much shorter but several times during a GC.  Execution Engine
Suspension
<gcServer enabled="true">
<gcConcurrent enabled="false">
 <gcConcurrent enabled="true"> 
 Config Setting
Non-Concurrent Workstation GC      On a single
processor
(fallback)
نظرات اشتراک‌ها
روش امن نگهداری پسورد کاربران
پیاده سازی روش گفته شده در این سایت :
/* 
 * Password Hashing With PBKDF2 (http://crackstation.net/hashing-security.htm).
 * Copyright (c) 2013, Taylor Hornby
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, 
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation 
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 * POSSIBILITY OF SUCH DAMAGE.
 */

using System;
using System.Text;
using System.Security.Cryptography;

namespace PasswordHash
{
    /// <summary>
    /// Salted password hashing with PBKDF2-SHA1.
    /// Author: havoc AT defuse.ca
    /// www: http://crackstation.net/hashing-security.htm
    /// Compatibility: .NET 3.0 and later.
    /// </summary>
    public class PasswordHash
    {
        // The following constants may be changed without breaking existing hashes.
        public const int SALT_BYTE_SIZE = 24;
        public const int HASH_BYTE_SIZE = 24;
        public const int PBKDF2_ITERATIONS = 1000;

        public const int ITERATION_INDEX = 0;
        public const int SALT_INDEX = 1;
        public const int PBKDF2_INDEX = 2;

        /// <summary>
        /// Creates a salted PBKDF2 hash of the password.
        /// </summary>
        /// <param name="password">The password to hash.</param>
        /// <returns>The hash of the password.</returns>
        public static string CreateHash(string password)
        {
            // Generate a random salt
            RNGCryptoServiceProvider csprng = new RNGCryptoServiceProvider();
            byte[] salt = new byte[SALT_BYTE_SIZE];
            csprng.GetBytes(salt);

            // Hash the password and encode the parameters
            byte[] hash = PBKDF2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE);
            return PBKDF2_ITERATIONS + ":" +
                Convert.ToBase64String(salt) + ":" +
                Convert.ToBase64String(hash);
        }

        /// <summary>
        /// Validates a password given a hash of the correct one.
        /// </summary>
        /// <param name="password">The password to check.</param>
        /// <param name="correctHash">A hash of the correct password.</param>
        /// <returns>True if the password is correct. False otherwise.</returns>
        public static bool ValidatePassword(string password, string correctHash)
        {
            // Extract the parameters from the hash
            char[] delimiter = { ':' };
            string[] split = correctHash.Split(delimiter);
            int iterations = Int32.Parse(split[ITERATION_INDEX]);
            byte[] salt = Convert.FromBase64String(split[SALT_INDEX]);
            byte[] hash = Convert.FromBase64String(split[PBKDF2_INDEX]);

            byte[] testHash = PBKDF2(password, salt, iterations, hash.Length);
            return SlowEquals(hash, testHash);
        }

        /// <summary>
        /// Compares two byte arrays in length-constant time. This comparison
        /// method is used so that password hashes cannot be extracted from
        /// on-line systems using a timing attack and then attacked off-line.
        /// </summary>
        /// <param name="a">The first byte array.</param>
        /// <param name="b">The second byte array.</param>
        /// <returns>True if both byte arrays are equal. False otherwise.</returns>
        private static bool SlowEquals(byte[] a, byte[] b)
        {
            uint diff = (uint)a.Length ^ (uint)b.Length;
            for (int i = 0; i < a.Length && i < b.Length; i++)
                diff |= (uint)(a[i] ^ b[i]);
            return diff == 0;
        }

        /// <summary>
        /// Computes the PBKDF2-SHA1 hash of a password.
        /// </summary>
        /// <param name="password">The password to hash.</param>
        /// <param name="salt">The salt.</param>
        /// <param name="iterations">The PBKDF2 iteration count.</param>
        /// <param name="outputBytes">The length of the hash to generate, in bytes.</param>
        /// <returns>A hash of the password.</returns>
        private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes)
        {
            Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt);
            pbkdf2.IterationCount = iterations;
            return pbkdf2.GetBytes(outputBytes);
        }
    }
}