อักขระที่อนุญาตให้ใช้ในคุกกี้คืออะไร


301

อักขระที่อนุญาตในทั้งชื่อคุกกี้และค่าคืออะไร พวกเขาเหมือนกันกับ URL หรือบางส่วนย่อยทั่วไป?

เหตุผลที่ฉันถามคือเมื่อเร็ว ๆ นี้ฉันพบพฤติกรรมแปลก ๆ บางอย่างกับคุกกี้ที่มี-ชื่ออยู่และฉันแค่สงสัยว่าเป็นสิ่งที่เบราว์เซอร์ระบุหรือรหัสของฉันผิด

คำตอบ:


391

คนนี้เป็นกุ๊กกิ๊ก:

คุณอาจคิดว่ามันควรจะเป็น แต่จริงๆแล้วมันไม่ได้เลย!

อักขระที่อนุญาตในทั้งชื่อคุกกี้และค่าคืออะไร

ตาม Netscape cookie_specโบราณNAME=VALUEสตริงทั้งหมดคือ:

ลำดับของอักขระที่ไม่รวมเซมิโคลอนเครื่องหมายจุลภาคและ white space

ดังนั้น-ควรใช้งานได้และดูเหมือนว่าจะใช้ได้ในเบราว์เซอร์ที่ฉันได้มาที่นี่ คุณมีปัญหากับที่ไหน

โดยนัยจากข้างต้น:

  • =ถูกกฎหมายที่จะรวมถึง แต่อาจคลุมเครือ เบราว์เซอร์จะแบ่งชื่อและค่าบน=สัญลักษณ์แรกในสตริงเสมอดังนั้นในทางปฏิบัติคุณสามารถใส่=สัญลักษณ์ในค่าได้ แต่ไม่ใช่ชื่อ

สิ่งที่ไม่ได้กล่าวถึงเนื่องจาก Netscape แย่มากในการเขียนรายละเอียด แต่ดูเหมือนว่าจะได้รับการสนับสนุนอย่างต่อเนื่องโดยเบราว์เซอร์:

  • NAME หรือ VALUE อาจเป็นสตริงว่างเปล่า

  • ถ้าไม่มี=สัญลักษณ์ในสตริงที่ทุกเบราว์เซอร์รักษามันเป็นคุกกี้ที่มีชื่อเปล่าสตริงคือเป็นเช่นเดียวกับSet-Cookie: fooSet-Cookie: =foo

  • เมื่อเบราว์เซอร์แสดงคุกกี้ที่มีชื่อว่างเปล่ามันจะตัดเครื่องหมายเท่ากับ ดังนั้นbegetsSet-Cookie: =barCookie: bar

  • เครื่องหมายจุลภาคและช่องว่างในชื่อและค่าดูเหมือนจริงจะใช้งานได้แม้ว่าช่องว่างรอบเครื่องหมายเท่ากับจะถูกตัดแต่ง

  • ตัวควบคุม ( \x00การ\x1Fบวก\x7F) จะไม่ได้รับอนุญาต

สิ่งที่ไม่ได้กล่าวถึงและเบราว์เซอร์ไม่สอดคล้องกันโดยสิ้นเชิงคืออักขระที่ไม่ใช่ ASCII (Unicode):

  • ใน Opera และ Google Chrome พวกเขาจะถูกเข้ารหัสเป็นส่วนหัวของคุกกี้ด้วย UTF-8;
  • ใน IE หน้ารหัสเริ่มต้นของเครื่องจะใช้ (เฉพาะโลแคลและไม่ใช้ UTF-8)
  • Firefox (และเบราว์เซอร์ที่ใช้ Mozilla อื่น ๆ ) ใช้ไบต์ต่ำของจุดรหัส UTF-16 แต่ละจุดด้วยตัวของมันเอง (ดังนั้น ISO-8859-1 ก็โอเค แต่สิ่งอื่น ๆ ก็ยุ่งเหยิง);
  • Safari ไม่ยอมส่งคุกกี้ใด ๆ ที่มีอักขระที่ไม่ใช่ ASCII

ดังนั้นในทางปฏิบัติคุณไม่สามารถใช้อักขระที่ไม่ใช่ ASCII ในคุกกี้ได้เลย หากคุณต้องการใช้ Unicode, รหัสควบคุมหรือลำดับไบต์อื่น ๆ cookie_spec ต้องการให้คุณใช้รูปแบบการเข้ารหัสแบบ ad-hoc ที่คุณเลือกเองและแนะนำการเข้ารหัส URL (ตามที่ผลิตโดย JavaScript encodeURIComponent) เป็นตัวเลือกที่สมเหตุสมผล

ในแง่ของมาตรฐานที่เกิดขึ้นจริงมีความพยายามสองสามครั้งที่จะประมวลผลพฤติกรรมของคุกกี้

  • RFC 2109เป็นความพยายามในการแปลงรหัสและแก้ไข Netscape cookie_spec ดั้งเดิม ในหลายมาตรฐานตัวอักษรพิเศษมากขึ้นนี้จะไม่ได้รับอนุญาตที่จะใช้RFC 2616ราชสกุล (ก-จะยังคงได้รับอนุญาตให้มี) และมีเพียงค่าอาจจะระบุไว้ในที่ยกสตริงกับตัวละครอื่น ๆ ไม่มีเบราว์เซอร์ใดที่ใช้งานข้อ จำกัด การจัดการสตริงและคำยกเว้นแบบพิเศษที่ยกมาหรือคุณสมบัติใหม่ในข้อมูลจำเพาะนี้

  • RFC 2965เป็นอีกสิ่งหนึ่งที่สามารถจัดการได้ถึง 2109 รายการและเพิ่มคุณสมบัติเพิ่มเติมภายใต้รูปแบบ 'คุกกี้รุ่น 2' ไม่มีใครเคยทำเช่นนั้นมาก่อน ข้อมูลจำเพาะนี้มีข้อ จำกัด โทเค็นและสตริงที่อ้างอิงเหมือนกับรุ่นก่อนหน้าและเป็นเพียงเรื่องไร้สาระมากมาย

  • RFC 6265เป็นความพยายามในยุค HTML5 ในการแก้ไขปัญหาทางประวัติศาสตร์ มันยังไม่ตรงกับความเป็นจริง แต่มันก็ยังดีกว่าความพยายามก่อนหน้านี้ - อย่างน้อยก็เป็นเซตย่อยที่เหมาะสมของสิ่งที่เบราว์เซอร์รองรับไม่แนะนำไวยากรณ์ใด ๆ ที่ควรจะใช้งานได้ แต่ไม่เหมือน .

ใน 6265 ชื่อคุกกี้ยังคงถูกระบุเป็น RFC 2616 tokenซึ่งหมายความว่าคุณสามารถเลือกได้จากตัวอักษรบวก:

!#$%&'*+-.^_`|~

ในค่าคุกกี้มันจะแบนตัวควบคุม (กรองโดยเบราว์เซอร์) อย่างเป็นทางการและอักขระที่ไม่ใช่ ASCII มันยังคงมีข้อห้ามของ cookie_spec ในช่องว่างเครื่องหมายจุลภาคและเซมิโคลอนรวมถึงความเข้ากันได้กับไอดีที่ไม่ดีที่ใช้ RFCs ก่อนหน้านี้มันยังห้ามแบ็กสแลชและเครื่องหมายคำพูดนอกเหนือจากเครื่องหมายคำพูดที่ตัดค่าทั้งหมด ค่าไม่ใช่รูปแบบการเข้ารหัส) ดังนั้นนั่นจะทำให้คุณมีตัวอักษรผสมบวก:

!#$%&'()*+-./:<=>?@[]^_`{|}~

ในโลกแห่งความเป็นจริงเรายังคงใช้ Netscape cookie_spec ดั้งเดิมและที่เลวร้ายที่สุดดังนั้นรหัสที่ใช้คุกกี้ควรเตรียมพร้อมที่จะพบกับสิ่งใดมาก แต่สำหรับรหัสที่ผลิตคุกกี้ขอแนะนำให้ติดกับชุดย่อยใน RFC 6265


@bobince คุณหมายถึงว่า RFC ระบุว่าค่าคุกกี้สามารถมี;อักขระได้ตราบใดที่มันล้อมรอบด้วยเครื่องหมายคำพูดคู่หรือไม่ เป็นเช่นนี้:Set-Cookie: Name=Va";"lue; Max-Age=3600
Pacerier

@Pacerier: Name="Va;lue"; max-age...ค่าทั้งหมดจะต้องมีการยกสตริงดังนั้นจึงจะต้องมีการ มันไม่ทำงานในเบราว์เซอร์และไม่ได้รับอนุญาตใน RFC 6265 ซึ่งเสนอให้แทนที่ 2965 และพยายามสะท้อนความเป็นจริงให้ดีขึ้น
bobince

@bince - ฉันรู้ว่านี่เก่า แต่ฉันอ่านคำตอบของคุณอย่างถูกต้องเพื่อหมายความว่าช่องว่างไม่ได้รับอนุญาตทางเทคนิคในค่าคุกกี้หรือไม่ "ไม่รวมเซมิโคลอนเครื่องหมายจุลภาคและช่องว่างสีขาว " [การเน้นของฉัน]
Adam Rackis

1
@ อดัม: ใช่ถ้าคุณไปตามข้อมูลจำเพาะของ Netscape หรือ RFC 6265 ไม่อนุญาตให้ใช้ช่องว่างในค่าคุกกี้แบบดิบ (ยกเลิกการ DQUOTEd) มันทำงานได้ไม่ดีในเบราว์เซอร์ที่ฉันได้ลอง แต่ฉันจะไม่พึ่งพา
bobince

2
RFC 6265กำหนด token เป็น1*<any CHAR except CTLs or separators>และแยกเป็น(, ), <, >, @, ,, ;, :, \, ", /, [, ], ?, =, {, }, SPและHTเพื่อให้ชื่อคุกกี้ควรจะ alphanums บวก!#$%&'*+-.?^_`|~
กาน Quan

28

ใน ASP.Net คุณสามารถใช้System.Web.HttpUtilityเข้ารหัสค่าคุกกี้ได้อย่างปลอดภัยก่อนที่จะเขียนลงในคุกกี้และแปลงกลับเป็นรูปแบบดั้งเดิมเมื่ออ่านออก

// Encode
HttpUtility.UrlEncode(cookieData);

// Decode
HttpUtility.UrlDecode(encodedCookieData);

สิ่งนี้จะหยุดเครื่องหมายและเครื่องหมายเท่ากับการแบ่งค่าเป็นคู่ของชื่อ / ค่าตามที่เขียนลงในคุกกี้


1
เพียงหนึ่งโน้ต asp.net ภายในใช้การเข้ารหัส hex แทน UrlEncode เมื่อเก็บคุกกี้การตรวจสอบสิทธิ์ referenceource.microsoft.com # System.Web / Security / …ดังนั้นอาจมีบางกรณีที่การเข้ารหัส URL ไม่ตัด
ปีเตอร์

17

ฉันคิดว่ามันเป็นเบราว์เซอร์ที่เฉพาะเจาะจงโดยทั่วไป เพื่อให้ปลอดภัยโดย base64 เข้ารหัสวัตถุ JSON และเก็บทุกอย่างไว้ในนั้น ด้วยวิธีนี้คุณเพียงแค่ต้องถอดรหัสและวิเคราะห์ JSON อักขระทั้งหมดที่ใช้ใน base64 ควรเล่นได้ดีที่สุดหากไม่ใช่เบราว์เซอร์ทั้งหมด


คำตอบนี้ดูเหมือนจะเป็นคำตอบที่สอดคล้องกันในเบราว์เซอร์ ฉันรู้เรื่องนี้หลังจากทำงานหลายชั่วโมงพยายามหาวิธีแก้ปัญหาอย่างรวดเร็ว: ฉันไม่ได้รับเลย เพียงทำตามที่แนะนำไว้ข้างต้นเพื่อช่วยให้คุณไม่ต้องยุ่งยาก
ยิ้ม

ไม่ได้ลองสิ่งนี้ แต่ฉันอ่านบทความอื่น ๆ เกี่ยวกับเรื่องนี้ว่าการเข้ารหัส base64 ใช้ได้กับอักขระ ascii เท่านั้น
user984003

11

นี่มันเป็นในขณะที่คำไม่กี่คำที่เป็นไปได้ มุ่งเน้นไปที่ตัวละครที่ไม่ต้องการหลบหนี:

สำหรับคุ๊กกี้:

abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789!#$%&'()*+-./:<>?@[]^_`{|}~

สำหรับ URL

abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789.-_~!$&'()*+,;=:@

สำหรับคุกกี้และ URL (สี่แยก)

abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789!$&'()*+-.:@_~

นั่นคือวิธีที่คุณตอบ

โปรดทราบว่าสำหรับคุกกี้นั้นจะมีการลบ=เนื่องจากมักจะใช้เพื่อตั้งค่าคุกกี้

สำหรับ URL นี้ = ถูกเก็บไว้ เห็นได้ชัดว่าแยกได้โดยไม่ต้อง

var chars = "abdefghijklmnqrstuvxyz"; chars += chars.toUpperCase() + "0123456789" + "!$&'()*+-.:@_~";

ปรากฎว่าการหลบหนียังคงเกิดขึ้นและเกิดขึ้นโดยไม่คาดคิดโดยเฉพาะในสภาพแวดล้อมคุกกี้ Java ซึ่งคุกกี้ถูกห่อด้วยเครื่องหมายคำพูดคู่หากพบอักขระตัวสุดท้าย

เพื่อความปลอดภัยเพียงใช้ A-Za-z1-9 นั่นคือสิ่งที่ฉันจะทำ


Safari Safari เป็นเบราว์เซอร์ปัญหาเดียวของฉันเบราว์เซอร์อื่น ๆ ทั้งหมดทำงานได้ดี ฉันต้อง UrlEncode และ UrlDecode คุกกี้ของฉันเพื่อจัดการกับ = เครื่องหมายและช่องว่าง เหมือน Base64Encode ในคุกกี้ (Safari ที่จำเป็นเท่านั้น this- เบราว์เซอร์อื่น ๆ ทำงานได้ดีที่มีและไม่มีคุกกี้เข้ารหัส.)
Sql อินเตอร์เนต

มันจะดีกว่าถ้าคุณทำรายการแหล่งข้อมูลที่นำไปสู่คำตอบของคุณ!
Loc

1
@Loc มากกว่า 3 ชั่วโมงของการทดลองและตรวจสอบ
mmm

10

ใหม่กว่าrfc6265เผยแพร่ในเดือนเมษายน 2011:

cookie-header = "Cookie:" OWS cookie-string OWS
cookie-string = cookie-pair *( ";" SP cookie-pair )
cookie-pair  = cookie-name "=" cookie-value
cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )

cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
                   ; US-ASCII characters excluding CTLs,
                   ; whitespace DQUOTE, comma, semicolon,
                   ; and backslash

หากคุณดู@bobinceตอบคุณจะเห็นว่าข้อ จำกัด ที่ใหม่กว่าเข้มงวดกว่านี้


6

คุณไม่สามารถใส่ ";" ในฟิลด์ค่าของคุกกี้ชื่อที่จะตั้งเป็นสตริงจนถึง ";" ในเบราว์เซอร์ส่วนใหญ่ ...


1

ข้อกำหนดของคุกกี้มี 2 รุ่น
1. คุกกี้รุ่น 0 คุกกี้ aka Netscape,
2. รุ่นที่ 1 หรือที่เรียกว่าคุกกี้ RFC 2965
ในรุ่น 0 ชื่อและส่วนค่าของคุกกี้คือลำดับของอักขระไม่รวมอัฒภาค, เครื่องหมายจุลภาค, เครื่องหมายเท่ากับและช่องว่าง ถ้าไม่ได้ใช้กับอัญประกาศคู่
รุ่น 1 มีความซับซ้อนมากขึ้นคุณสามารถตรวจสอบได้ที่นี่
ในรายละเอียดรุ่นสำหรับส่วนค่าชื่อเกือบจะเหมือนกันยกเว้นชื่อไม่สามารถเริ่มต้นด้วย $ sign


มันบอกว่าค่าจะต้องยกเว้นเท่ากับเข้าสู่ระบบในรุ่น 0?
Gili

1

มีปัญหาอื่นที่น่าสนใจเกี่ยวกับ IE และ Edge ดูเหมือนว่าคุกกี้ที่มีชื่อที่มีระยะเวลามากกว่า 1 รอบจะถูกลบอย่างเงียบ ๆ ดังนั้นวิธีนี้ใช้งานได้:

cookie_name_a = valuea

ขณะนี้จะลดลง

cookie.name.a = valuea


คงจะดีมากถ้าคุณเพิ่มเวอร์ชันเบราว์เซอร์ที่แน่นอนเพื่อให้เราทำซ้ำเนื่องจากพฤติกรรมของเบราว์เซอร์ไม่สอดคล้องกับคุกกี้
เจอรัลด์

0

มันง่ายมาก:

<cookie-name> สามารถเป็นอักขระ US-ASCII ใดก็ได้ยกเว้นอักขระควบคุม (CTLs), ช่องว่างหรือแท็บ และต้องไม่มีอักขระตัวคั่นดังนี้: () <> @,; : \ "/ []? = {}

<cookie-value> สามารถตั้งค่าเป็นเครื่องหมายคำพูดคู่และตัวอักษร US-ASCII ใด ๆ ที่ไม่รวม CTL, ช่องว่าง, เครื่องหมายคำพูดคู่, เครื่องหมายจุลภาค, เครื่องหมายอัฒภาคและเครื่องหมายแบ็กสแลชได้ การเข้ารหัส: การนำไปใช้งานจำนวนมากทำการเข้ารหัส URL บนค่าคุกกี้อย่างไรก็ตามไม่จำเป็นต้องใช้ตามข้อกำหนด RFC มันช่วยให้เป็นไปตามข้อกำหนดเกี่ยวกับตัวละครที่ได้รับอนุญาต

Link: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Directives


0

อีกหนึ่งข้อพิจารณา ฉันเพิ่งใช้รูปแบบที่ข้อมูลสำคัญบางอย่างโพสต์ไปยังสคริปต์ PHP ที่จำเป็นในการแปลงและส่งคืนเป็นคุกกี้ที่เข้ารหัสซึ่งใช้ค่า base64 ทั้งหมดที่ฉันคิดว่ารับประกันว่า "ปลอดภัย" ดังนั้นฉันจึงเข้ารหัสรายการข้อมูลโดยใช้ RC4 ผลลัพธ์ผ่าน base64_encode และนำคุกกี้กลับมาที่เว็บไซต์อย่างมีความสุขการทดสอบดูเหมือนจะทำได้ดีจนกระทั่งสตริงที่เข้ารหัส base64 มีสัญลักษณ์ "+" สตริงถูกเขียนลงในหน้าคุกกี้โดยไม่มีปัญหาการใช้การวินิจฉัยเบราว์เซอร์ที่ฉันสามารถทำได้ ตรวจสอบว่าคุกกี้ถูกเขียนไม่เปลี่ยนแปลงจากนั้นเมื่อหน้าถัดมาเรียกว่า PHP ของฉันและรับคุกกี้ผ่านอาร์เรย์ $ _COOKIE ฉันก็ติดขัดเพื่อค้นหาสตริงที่ตอนนี้ไม่มีเครื่องหมาย "+" ทุกตัวของอักขระนั้นถูกแทนที่ด้วย พื้นที่ ASCII

เมื่อพิจารณาถึงจำนวนข้อร้องเรียนที่ไม่ได้รับการแก้ไขที่คล้ายกันที่ฉันได้อ่านอธิบายสถานการณ์นี้ตั้งแต่นั้นมามักจะอ้างอิงจำนวนมากเพื่อใช้ base64 กับ "ปลอดภัย" จัดเก็บข้อมูลโดยพลการในคุกกี้ฉันคิดว่าฉันจะชี้ปัญหา

หลังจากที่คุณทำการเข้ารหัสที่คุณต้องการทำกับข้อมูลแล้วใช้ base64_encode เพื่อทำให้มัน "ปลอดภัยสำหรับคุกกี้" ให้รันสตริงเอาต์พุตผ่านสิ่งนี้ ...

// from browser to PHP. substitute troublesome chars with 
// other cookie safe chars, or vis-versa.  

function fix64($inp) {
    $out =$inp;
    for($i = 0; $i < strlen($inp); $i++) {
        $c = $inp[$i];
        switch ($c) {
            case '+':  $c = '*'; break; // definitly won't transfer!
            case '*':  $c = '+'; break;

            case '=':  $c = ':'; break; // = symbol seems like a bad idea
            case ':':  $c = '='; break;

            default: continue;
            }
        $out[$i] = $c;
        }
    return $out;
    }

ที่นี่ฉันเพียงแค่แทนที่ "+" (และฉันตัดสินใจ "=" เช่นกัน) ด้วยอักขระ "คุกกี้ปลอดภัย" อื่น ๆ ก่อนที่จะส่งคืนค่าที่เข้ารหัสไปยังหน้าเพื่อใช้เป็นคุกกี้ โปรดทราบว่าความยาวของสตริงที่ประมวลผลไม่เปลี่ยนแปลง เมื่อหน้าเดียวกัน (หรืออีกหน้าหนึ่งบนไซต์) เรียกใช้สคริปต์ PHP ของฉันอีกครั้งฉันจะสามารถกู้คืนคุกกี้นี้ได้โดยไม่ขาดอักขระ ฉันต้องจำไว้ว่าให้ส่งคุกกี้กลับผ่าน fix64 () สายเดียวที่ฉันสร้างขึ้นและจากนั้นฉันสามารถถอดรหัสได้ด้วย base64_decode ปกติ () ตามด้วยการถอดรหัสอื่น ๆ ในแบบแผนของคุณ

อาจมีการตั้งค่าบางอย่างที่ฉันสามารถทำได้ใน PHP ที่อนุญาตให้ base64 สตริงที่ใช้ในคุกกี้เพื่อถ่ายโอนกลับไปที่ PHP โดยไม่มีความเสียหาย ในช่วงเวลานี้ได้ผล "+" อาจเป็นค่าคุกกี้ "ถูกกฎหมาย" แต่หากคุณมีความปรารถนาที่จะสามารถส่งสตริงดังกล่าวกลับไปที่ PHP (ในกรณีของฉันผ่านอาร์เรย์ $ _COOKIE) ฉันขอแนะนำให้ประมวลผลอีกครั้งเพื่อลบ อักขระที่ละเมิดและกู้คืนได้หลังจากการกู้คืน มีตัวเลือก "ปลอดภัยคุกกี้" อื่น ๆ อีกมากมายให้เลือก


0

หากคุณใช้ตัวแปรในภายหลังคุณจะพบว่าสิ่งที่ชอบpathจริง ๆ จะทำให้อักขระเน้นเสียงผ่านได้ แต่จริง ๆ แล้วจะไม่ตรงกับเส้นทางเบราว์เซอร์ สำหรับสิ่งที่คุณต้อง URIEncode พวกเขา ดังนั้นเช่นนี้:

  const encodedPath = encodeURI(myPath);
  document.cookie = `use_pwa=true; domain=${location.host}; path=${encodedPath};`

ตัวอักษร "ที่อนุญาต" อาจมีมากกว่าในสเป็ค แต่คุณควรอยู่ในข้อมูลจำเพาะและใช้สตริงที่เข้ารหัส URI เพื่อความปลอดภัย


-1

หลายปีที่ผ่านมา MSIE 5 หรือ 5.5 (และอาจเป็นได้ทั้งคู่) มีปัญหาร้ายแรงที่มี "-" ในบล็อก HTML หากคุณเชื่อ แม้ว่ามันจะไม่เกี่ยวข้องโดยตรงเนื่องจากเราเก็บ MD5 แฮช (ที่มีตัวอักษรและตัวเลขเท่านั้น) ในคุกกี้เพื่อค้นหาทุกอย่างในฐานข้อมูลฝั่งเซิร์ฟเวอร์


-2

ฉันลงเอยด้วยการใช้

cookie_value = encodeURIComponent(my_string);

และ

my_string = decodeURIComponent(cookie_value);

ดูเหมือนว่าจะใช้ได้กับตัวละครทุกประเภท ฉันมีปัญหาแปลก ๆ อย่างอื่นแม้จะมีตัวละครที่ไม่ใช่อัฒภาคหรือคอมมา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.