Mã hóa html

Vì các URL thường chứa các ký tự bên ngoài bộ ASCII nên URL phải được chuyển đổi thành định dạng ASCII hợp lệ

Mã hóa URL thay thế các ký tự ASCII không an toàn bằng "%" theo sau là hai chữ số thập lục phân

URL không thể chứa khoảng trắng. Mã hóa URL thường thay thế khoảng trắng bằng dấu cộng (+) hoặc bằng %20


Tự mình thử

Nếu bạn nhấp vào nút "Gửi" bên dưới, trình duyệt sẽ mã hóa URL đầu vào trước khi gửi đến máy chủ. Một trang tại máy chủ sẽ hiển thị đầu vào nhận được

Là con người, chúng ta có khả năng sinh ra để chọn ra những thông tin có giá trị từ những tình huống không mấy lý tưởng. Bộ não của chúng ta có thể xử lý những thứ chúng ta cần khi bỏ qua những điều vô nghĩa. Thật không may, các thành phần chính của web như HTML và HTTP không có khả năng tương thích và trên thực tế, không quá ngạc nhiên về điều này

Là lập trình viên, chúng ta cần thực hiện các bước bổ sung khi truyền dữ liệu đến một trang HTML để đảm bảo rằng nó không phá vỡ các quy ước HTML. Ngoài ra, khi gửi yêu cầu đến máy chủ, chúng ta có thể phải tuân thủ các quy tắc HTTP để đảm bảo máy chủ không từ chối yêu cầu web của chúng ta

Bài viết này sẽ giúp bạn tìm hiểu lớp

if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
7 và phân tích cách các phương thức của nó đang hoạt động với đầu vào của chúng ta để mã hóa/giải mã dữ liệu có khả năng bị phá vỡ

Encode/Decode là gì?

Mã hóa (Mã hóa) và Giải mã (giải mã) là hai mặt đối lập của cùng một quá trình. lấy đầu của người dùng và làm sạch nó cho người nhận dự kiến

Phương pháp mã hóa nhận một giá trị mà con người có thể đọc được và chuyển đổi thành các ký tự có thể gây trở ngại cho người nhận. Trong trường hợp HTML, các ký tự đó có thể là dấu trích dẫn (

if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
8 và
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
9)

Quên mã hóa thông tin đầu vào của người dùng là một câu hỏi điển hình đối với các cuộc tấn công xss (kịch bản chéo trang) trên nhiều trang web

Người dùng có thể nhập dữ liệu vào ứng dụng và trang web hiển thị dữ liệu đó mà không cần xác nhận tính toàn vẹn của nó trước đó. Chúng ta sẽ đi vào chi tiết hơn trong phần Mã hóa HTML của bài viết này

Quá trình giải mã đảo ngược quá trình mã hóa. Quá trình này lấy các ký tự đã được thay thế và hoàn nguyên chúng về giá trị ban đầu. Việc giải mã có thể hữu ích trong các tình huống mà giá trị ban đầu cần được xác minh bằng mắt người nhưng cuối cùng lại được gửi đến người nhận không phải là người lừa đảo

Chúng ta có thể thấy các URL được mã hóa với các giá trị như

if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
0, cho biết một khoảng trống trong URL của chúng ta. Một kẻ lừa đảo có thể cảm thấy khó đọc
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
1, nhưng giá trị ban đầu của nó là
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
0 rất tự nhiên

Chúng ta hãy đi sâu vào các chi tiết cụ thể về HTML Encode và URL Encode và cả hai khác nhau như thế nào ở phần tiếp theo

Các lớp tiện ích WebUtility và HttpUtility

NET Runtime có một lớp

if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
7 chứa các phương thức đầy đủ nhất trong. NET để thực hiện các nhiệm vụ mã hóa lõi được nhắm mục tiêu trên web. Nó là một phần của namepsace
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
2 và có thể được tìm thấy trong assembly
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
3

Ngoài ra còn có lớp

if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
4 được tìm thấy ở không gian tên
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
5 có thể thực hiện thêm mã hóa / giải mã dựa trên thuộc tính HTML, chuỗi truy vấn, JavaScript và các hoạt động khác sử dụng các loại
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
6, trong đó bao gồm các biến thể của

Vì lợi ích của bài viết này, chúng ta sẽ theo dõi sự phát triển của lớp

if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
7

mã hóa url

Chúng ta hãy xem phương thức

public static void HtmlEncode(string? value, TextWriter output)
{
    if (output == null)
    {
        throw new ArgumentNullException(nameof(output));
    }
    if (string.IsNullOrEmpty(value))
    {
        output.Write(value);
        return;
    }

    ReadOnlySpan valueSpan = value.AsSpan();

    // Don't create ValueStringBuilder if we don't have anything to encode
    int index = IndexOfHtmlEncodingChars(valueSpan);
    if (index == -1)
    {
        output.Write(value);
        return;
    }

    // For small inputs we allocate on the stack. In most cases a buffer three
    // times larger the original string should be sufficient as usually not all
    // characters need to be encoded.
    // For larger string we rent the input string's length plus a fixed
    // conservative amount of chars from the ArrayPool.
    ValueStringBuilder sb = value.Length < 80 ?
        new ValueStringBuilder(stackalloc char[256]) :
        new ValueStringBuilder(value.Length + 200);

    sb.Append(valueSpan.Slice(0, index));
    HtmlEncode(valueSpan.Slice(index), ref sb);

    output.Write(sb.AsSpan());
    sb.Dispose();
}
1 được tìm thấy trong lớp
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
7. Trong phương thức này, chúng ta sẽ xem những ký tự nào được coi là an toàn và những ký tự nào cần được thay đổi để tôn trọng người nhận URL của chúng ta

if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
0

Phần đáng chú ý nhất của phương thức là lời gọi đến phương thức

public static void HtmlEncode(string? value, TextWriter output)
{
    if (output == null)
    {
        throw new ArgumentNullException(nameof(output));
    }
    if (string.IsNullOrEmpty(value))
    {
        output.Write(value);
        return;
    }

    ReadOnlySpan valueSpan = value.AsSpan();

    // Don't create ValueStringBuilder if we don't have anything to encode
    int index = IndexOfHtmlEncodingChars(valueSpan);
    if (index == -1)
    {
        output.Write(value);
        return;
    }

    // For small inputs we allocate on the stack. In most cases a buffer three
    // times larger the original string should be sufficient as usually not all
    // characters need to be encoded.
    // For larger string we rent the input string's length plus a fixed
    // conservative amount of chars from the ArrayPool.
    ValueStringBuilder sb = value.Length < 80 ?
        new ValueStringBuilder(stackalloc char[256]) :
        new ValueStringBuilder(value.Length + 200);

    sb.Append(valueSpan.Slice(0, index));
    HtmlEncode(valueSpan.Slice(index), ref sb);

    output.Write(sb.AsSpan());
    sb.Dispose();
}
3. Các giá trị mà chúng ta có thể thêm vào URL một cách an toàn là gì?

if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;

Hóa ra tất cả mọi thứ ngoại trừ chữ và số ký tự, và các ký tự

public static void HtmlEncode(string? value, TextWriter output)
{
    if (output == null)
    {
        throw new ArgumentNullException(nameof(output));
    }
    if (string.IsNullOrEmpty(value))
    {
        output.Write(value);
        return;
    }

    ReadOnlySpan valueSpan = value.AsSpan();

    // Don't create ValueStringBuilder if we don't have anything to encode
    int index = IndexOfHtmlEncodingChars(valueSpan);
    if (index == -1)
    {
        output.Write(value);
        return;
    }

    // For small inputs we allocate on the stack. In most cases a buffer three
    // times larger the original string should be sufficient as usually not all
    // characters need to be encoded.
    // For larger string we rent the input string's length plus a fixed
    // conservative amount of chars from the ArrayPool.
    ValueStringBuilder sb = value.Length < 80 ?
        new ValueStringBuilder(stackalloc char[256]) :
        new ValueStringBuilder(value.Length + 200);

    sb.Append(valueSpan.Slice(0, index));
    HtmlEncode(valueSpan.Slice(index), ref sb);

    output.Write(sb.AsSpan());
    sb.Dispose();
}
4,
public static void HtmlEncode(string? value, TextWriter output)
{
    if (output == null)
    {
        throw new ArgumentNullException(nameof(output));
    }
    if (string.IsNullOrEmpty(value))
    {
        output.Write(value);
        return;
    }

    ReadOnlySpan valueSpan = value.AsSpan();

    // Don't create ValueStringBuilder if we don't have anything to encode
    int index = IndexOfHtmlEncodingChars(valueSpan);
    if (index == -1)
    {
        output.Write(value);
        return;
    }

    // For small inputs we allocate on the stack. In most cases a buffer three
    // times larger the original string should be sufficient as usually not all
    // characters need to be encoded.
    // For larger string we rent the input string's length plus a fixed
    // conservative amount of chars from the ArrayPool.
    ValueStringBuilder sb = value.Length < 80 ?
        new ValueStringBuilder(stackalloc char[256]) :
        new ValueStringBuilder(value.Length + 200);

    sb.Append(valueSpan.Slice(0, index));
    HtmlEncode(valueSpan.Slice(index), ref sb);

    output.Write(sb.AsSpan());
    sb.Dispose();
}
5,
public static void HtmlEncode(string? value, TextWriter output)
{
    if (output == null)
    {
        throw new ArgumentNullException(nameof(output));
    }
    if (string.IsNullOrEmpty(value))
    {
        output.Write(value);
        return;
    }

    ReadOnlySpan valueSpan = value.AsSpan();

    // Don't create ValueStringBuilder if we don't have anything to encode
    int index = IndexOfHtmlEncodingChars(valueSpan);
    if (index == -1)
    {
        output.Write(value);
        return;
    }

    // For small inputs we allocate on the stack. In most cases a buffer three
    // times larger the original string should be sufficient as usually not all
    // characters need to be encoded.
    // For larger string we rent the input string's length plus a fixed
    // conservative amount of chars from the ArrayPool.
    ValueStringBuilder sb = value.Length < 80 ?
        new ValueStringBuilder(stackalloc char[256]) :
        new ValueStringBuilder(value.Length + 200);

    sb.Append(valueSpan.Slice(0, index));
    HtmlEncode(valueSpan.Slice(index), ref sb);

    output.Write(sb.AsSpan());
    sb.Dispose();
}
6,
public static void HtmlEncode(string? value, TextWriter output)
{
    if (output == null)
    {
        throw new ArgumentNullException(nameof(output));
    }
    if (string.IsNullOrEmpty(value))
    {
        output.Write(value);
        return;
    }

    ReadOnlySpan valueSpan = value.AsSpan();

    // Don't create ValueStringBuilder if we don't have anything to encode
    int index = IndexOfHtmlEncodingChars(valueSpan);
    if (index == -1)
    {
        output.Write(value);
        return;
    }

    // For small inputs we allocate on the stack. In most cases a buffer three
    // times larger the original string should be sufficient as usually not all
    // characters need to be encoded.
    // For larger string we rent the input string's length plus a fixed
    // conservative amount of chars from the ArrayPool.
    ValueStringBuilder sb = value.Length < 80 ?
        new ValueStringBuilder(stackalloc char[256]) :
        new ValueStringBuilder(value.Length + 200);

    sb.Append(valueSpan.Slice(0, index));
    HtmlEncode(valueSpan.Slice(index), ref sb);

    output.Write(sb.AsSpan());
    sb.Dispose();
}
7,
public static void HtmlEncode(string? value, TextWriter output)
{
    if (output == null)
    {
        throw new ArgumentNullException(nameof(output));
    }
    if (string.IsNullOrEmpty(value))
    {
        output.Write(value);
        return;
    }

    ReadOnlySpan valueSpan = value.AsSpan();

    // Don't create ValueStringBuilder if we don't have anything to encode
    int index = IndexOfHtmlEncodingChars(valueSpan);
    if (index == -1)
    {
        output.Write(value);
        return;
    }

    // For small inputs we allocate on the stack. In most cases a buffer three
    // times larger the original string should be sufficient as usually not all
    // characters need to be encoded.
    // For larger string we rent the input string's length plus a fixed
    // conservative amount of chars from the ArrayPool.
    ValueStringBuilder sb = value.Length < 80 ?
        new ValueStringBuilder(stackalloc char[256]) :
        new ValueStringBuilder(value.Length + 200);

    sb.Append(valueSpan.Slice(0, index));
    HtmlEncode(valueSpan.Slice(index), ref sb);

    output.Write(sb.AsSpan());
    sb.Dispose();
}
8,
public static void HtmlEncode(string? value, TextWriter output)
{
    if (output == null)
    {
        throw new ArgumentNullException(nameof(output));
    }
    if (string.IsNullOrEmpty(value))
    {
        output.Write(value);
        return;
    }

    ReadOnlySpan valueSpan = value.AsSpan();

    // Don't create ValueStringBuilder if we don't have anything to encode
    int index = IndexOfHtmlEncodingChars(valueSpan);
    if (index == -1)
    {
        output.Write(value);
        return;
    }

    // For small inputs we allocate on the stack. In most cases a buffer three
    // times larger the original string should be sufficient as usually not all
    // characters need to be encoded.
    // For larger string we rent the input string's length plus a fixed
    // conservative amount of chars from the ArrayPool.
    ValueStringBuilder sb = value.Length < 80 ?
        new ValueStringBuilder(stackalloc char[256]) :
        new ValueStringBuilder(value.Length + 200);

    sb.Append(valueSpan.Slice(0, index));
    HtmlEncode(valueSpan.Slice(index), ref sb);

    output.Write(sb.AsSpan());
    sb.Dispose();
}
9 và
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
90 là không an toàn. Quay trở lại phương thức ban đầu
public static void HtmlEncode(string? value, TextWriter output)
{
    if (output == null)
    {
        throw new ArgumentNullException(nameof(output));
    }
    if (string.IsNullOrEmpty(value))
    {
        output.Write(value);
        return;
    }

    ReadOnlySpan valueSpan = value.AsSpan();

    // Don't create ValueStringBuilder if we don't have anything to encode
    int index = IndexOfHtmlEncodingChars(valueSpan);
    if (index == -1)
    {
        output.Write(value);
        return;
    }

    // For small inputs we allocate on the stack. In most cases a buffer three
    // times larger the original string should be sufficient as usually not all
    // characters need to be encoded.
    // For larger string we rent the input string's length plus a fixed
    // conservative amount of chars from the ArrayPool.
    ValueStringBuilder sb = value.Length < 80 ?
        new ValueStringBuilder(stackalloc char[256]) :
        new ValueStringBuilder(value.Length + 200);

    sb.Append(valueSpan.Slice(0, index));
    HtmlEncode(valueSpan.Slice(index), ref sb);

    output.Write(sb.AsSpan());
    sb.Dispose();
}
1, chúng ta có thể thấy điều gì đó sẽ xảy ra với tất cả các giá trị không mong muốn đó

  1. Đầu tiên, phương thức chuyển đổi các giá trị khoảng trắng thành các ký tự dấu cộng (
    if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
    {
        return true;
    }
    
    switch (ch)
    {
        case '-':
        case '_':
        case '.':
        case '!':
        case '*':
        case '(':
        case ')':
            return true;
    }
    
    return false;
    92)
  2. Cuối cùng, phương thức chuyển đổi các giá trị còn lại thành byte tương đương của chúng và sau đó nhận chuỗi giá trị. Mã hóa đạt được bằng cách sử dụng các phương thức
    if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
    {
        return true;
    }
    
    switch (ch)
    {
        case '-':
        case '_':
        case '.':
        case '!':
        case '*':
        case '(':
        case ')':
            return true;
    }
    
    return false;
    93 và
    if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
    {
        return true;
    }
    
    switch (ch)
    {
        case '-':
        case '_':
        case '.':
        case '!':
        case '*':
        case '(':
        case ')':
            return true;
    }
    
    return false;
    94

Bây giờ chúng ta hãy xem Mã hóa HTML và xem nó khác với Mã hóa URL như thế nào

Cũng ở trong lớp

if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
95, chúng ta sẽ tìm thấy phương thức
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
96. Chúng ta sử dụng phương thức này để nhận các giá trị mà chúng ta muốn hiển thị trong HTML hiện tại nhưng chúng ta không muốn đầu vào chúng ta làm hỏng cấu trúc HTML. Hãy xem cách. NET done this method

public static void HtmlEncode(string? value, TextWriter output)
{
    if (output == null)
    {
        throw new ArgumentNullException(nameof(output));
    }
    if (string.IsNullOrEmpty(value))
    {
        output.Write(value);
        return;
    }

    ReadOnlySpan valueSpan = value.AsSpan();

    // Don't create ValueStringBuilder if we don't have anything to encode
    int index = IndexOfHtmlEncodingChars(valueSpan);
    if (index == -1)
    {
        output.Write(value);
        return;
    }

    // For small inputs we allocate on the stack. In most cases a buffer three
    // times larger the original string should be sufficient as usually not all
    // characters need to be encoded.
    // For larger string we rent the input string's length plus a fixed
    // conservative amount of chars from the ArrayPool.
    ValueStringBuilder sb = value.Length < 80 ?
        new ValueStringBuilder(stackalloc char[256]) :
        new ValueStringBuilder(value.Length + 200);

    sb.Append(valueSpan.Slice(0, index));
    HtmlEncode(valueSpan.Slice(index), ref sb);

    output.Write(sb.AsSpan());
    sb.Dispose();
}

Chúng ta có thể tìm thấy phần thú vị của phương thức

if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
96 chính là lệnh gọi tới phương thức
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
98

if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
9

Quá trình Mã hóa HTML đảm bảo rằng các ký tự

if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
8,
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
9,
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
01,
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
02 và
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
03 được gắn cờ phải được thay thế bởi các ký tự HTML thân thiện với chúng. Giá trị nào thay thế các ký tự này?

if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
0

Các giá trị được mã hóa HTML sẽ bắt đầu bằng dấu và (

if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
03) và kết thúc bằng dấu chấm phẩy (
if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
{
    return true;
}

switch (ch)
{
    case '-':
    case '_':
    case '.':
    case '!':
    case '*':
    case '(':
    case ')':
        return true;
}

return false;
06)

Phần kết luận

Như chúng ta đã thấy trong quá trình phát triển URL Encode và HTML Encode, chúng ta đều thực hiện mục tiêu cuối cùng là thay đổi giá trị để đảm bảo an toàn cho người nhận

Trong HTML Encode, chúng ta thay đổi các ký tự có khả năng phá vỡ cấu trúc của trang HTML hiện có để khách hàng có thể hiển thị chúng một cách an toàn

Trong URL Encode, chúng ta thay đổi các giá trị có thể vi phạm tính liên tục của URL, khiến người dùng nhận đủ giá trị URL sai

Nếu bạn đang tìm thấy các hành vi lạ trong các trang ASP. NET được hiển thị của mình, bạn có thể muốn kiểm tra xem bạn có đang mã hóa các giá trị đúng cách hay không. May mắn thay, người dùng ASP. NET đã được mã hóa tự động khi sử dụng Razor, vì vậy đây không phải là vấn đề phổ biến mà là điều cần lưu ý

Nếu máy chủ từ chối yêu cầu của bạn, có thể có các giá trị trong URL của bạn đang phá vỡ tính hoàn chỉnh của nó. Kiểm tra các ký tự được đề cập ở trên và đảm bảo mã hóa URL của bạn trước khi thực hiện yêu cầu của bạn