ในส่วนหนึ่งของซีรีส์นี้ เราได้แนะนำ Devise โดยใช้แอปตัวอย่างเพื่อสำรวจโมดูล ผู้ช่วยเหลือ มุมมอง ตัวควบคุม และเส้นทาง
ในส่วนนี้ เราจะสำรวจการใช้งาน Devise ขั้นสูงเพิ่มเติม โดยเฉพาะการใช้ OmniAuth, การตรวจสอบสิทธิ์ API และ Authtrail
มาดำดิ่งกันเลย!
การรับรองความถูกต้องด้วย OmniAuth สำหรับ Ruby
ทุกวันนี้ เว็บแอปพลิเคชันเกือบทุกตัวที่คุณเจอจะเสนอตัวเลือกให้คุณเข้าสู่ระบบผ่านผู้ให้บริการตรวจสอบสิทธิ์ที่มีให้เลือกมากมาย ตั้งแต่โซเชียลเน็ตเวิร์กเช่น Twitter และ Facebook ไปจนถึง Google, GitHub และอื่นๆ อีกมากมาย
ในหลายกรณี การรับรองความถูกต้องของผู้ให้บริการหลายรายที่สะดวกสบายนี้ขับเคลื่อนโดยไลบรารีที่เรียกว่า OmniAuth OmniAuth เป็นไลบรารีการตรวจสอบสิทธิ์ที่ยืดหยุ่นและทรงพลังสำหรับ Ruby ที่ช่วยให้คุณสามารถผสานรวมกับผู้ให้บริการภายนอกหลายราย
โดยมี API ที่เรียบง่ายและเป็นหนึ่งเดียวสำหรับการเชื่อมต่อกับผู้ให้บริการ OAuth ต่างๆ OmniAuth มีประโยชน์อย่างยิ่งในสถานการณ์ที่คุณต้องการให้ผู้ใช้มีตัวเลือกในการลงทะเบียนหรือเข้าสู่ระบบโดยใช้บัญชีโซเชียลมีเดียของพวกเขา ด้วย OmniAuth คุณสามารถเพิ่มฟังก์ชันการเข้าสู่ระบบโซเชียลให้กับแอปพลิเคชัน Rails ของคุณได้อย่างง่ายดาย
เมื่อใช้ OmniAuth ร่วมกับ Devise gem การจัดการการรับรองความถูกต้องและการอนุญาตผู้ใช้จะง่ายยิ่งขึ้นไปอีก คุณสามารถใช้ประโยชน์จากคุณสมบัติการตรวจสอบสิทธิ์ในตัวของ Devise ได้ในขณะที่ใช้ OmniAuth สำหรับตัวเลือกการลงชื่อเข้าใช้ของผู้ให้บริการภายนอก
เริ่มต้นใช้งาน OmniAuth และ Devise
ดังที่ได้กล่าวไปแล้ว OmniAuth ช่วยให้คุณสามารถทำงานร่วมกับผู้ให้บริการตรวจสอบความถูกต้องบุคคลที่สามจำนวนหนึ่งได้ สำหรับวัตถุประสงค์ของบทความนี้ เราจะใช้ GitHub
ติดตั้ง OmniAuth Gems
ใน 03 ของแอปของคุณ ให้เพิ่มบรรทัดต่อไปนี้:
และหากคุณใช้ OmniAuth 2.0+ คุณจะต้องเพิ่ม:
18รหัส> gem รับรองว่า 25 ใดๆ คำขอที่ส่งไปยังโฟลว์ OAuth ถูกปิดใช้งาน นอกจากนี้ยังแทรกตัวตรวจสอบโทเค็น Rails CSRF ก่อนขั้นตอนการร้องขอ OAuth การดำเนินการทั้งสองนี้มีจุดมุ่งหมายเพื่อลดการโจมตีการปลอมแปลงข้ามไซต์ที่มุ่งเป้าไปที่ขั้นตอนการตรวจสอบสิทธิ์ OAuth
จากนั้นรัน 35 เพื่อติดตั้งอัญมณี
สร้างแอป GitHub OAuth ใหม่
ตอนนี้เราต้องสร้างแอป OAuth ใหม่บน GitHub แอปนี้จะทำหน้าที่เป็นผู้ใช้ที่มีสิทธิ์การตรวจสอบสิทธิ์ซึ่งสามารถเพิกถอนได้ง่ายหากจำเป็น
ขั้นตอนแรกคือไปที่หน้าการตั้งค่าใต้โปรไฟล์บัญชี GitHub ของคุณ จากนั้นที่เมนูด้านซ้าย ให้คลิกที่ "การตั้งค่าสำหรับนักพัฒนา" คุณจะเห็นหน้าจอเหมือนกับภาพด้านล่างนี้ ซึ่งคุณสามารถสร้างแอป OAuth ใหม่ได้:

เมื่อคุณคลิกที่ "ลงทะเบียนแอปพลิเคชันใหม่" คุณจะได้หน้าจอเช่นนี้:

กรอกรายละเอียดแบบฟอร์มดังนี้:
- ชื่อแอปพลิเคชัน - ตั้งชื่อที่เหมาะสมให้กับแอป OAuth ใหม่ของคุณ
- URL หน้าแรก - สำหรับตอนนี้ ให้ใช้
44. ในการใช้งานจริง คุณจะต้องใช้ URL หน้าแรกที่แท้จริงของแอป - คำอธิบายแอปพลิเคชัน - ไม่จำเป็น แต่คุณยังคงมีแอปได้หากคุณมีแอปจำนวนมากและจำเป็นต้องแยกความแตกต่างระหว่างแอปเหล่านั้น
- URL โทรกลับการอนุญาต - นี่เป็นอินพุตที่จำเป็น และโดยทั่วไปจะเป็นไปตามรูปแบบ URL โทรกลับ OAuth เช่น
57. อย่างไรก็ตาม ผู้ให้บริการ OAuth บางรายเช่น Google อาจไม่ปฏิบัติตามรูปแบบนี้ ดังนั้นคุณจึงต้องรับทราบไว้
เมื่อเสร็จแล้วให้คลิกที่ "ลงทะเบียนใบสมัคร" ในหน้าจอต่อไปนี้ ให้สร้างความลับของแอปใหม่และจดบันทึกไว้ในที่ที่ปลอดภัย (ซึ่งจะแสดงให้คุณเห็นเพียงครั้งเดียว)
กำหนดค่า Devise Initializer
เปิด Devise Initializer 67 และนำทางไปยังส่วน OmniAuth เฉพาะสำหรับ GitHub มันมีแนวโน้มที่จะถูกใส่ความคิดเห็น ดังนั้นอย่าใส่ความคิดเห็นและแก้ไขด้วยรหัสและความลับของแอป GitHub OAuth ใหม่ของคุณ:
สร้างตัวควบคุมการโทรกลับ OmniAuth
หากคุณได้สร้าง Devise controllers แล้ว คุณจะพบ 71 พร้อมให้คุณปรับแต่งได้ตามต้องการ หากไม่มีของคุณ เพียงสร้างด้วยตนเอง และแก้ไขดังนี้:
บางสิ่งที่ควรทราบเกี่ยวกับโค้ดด้านบน:
85รหัส> เป็นวิธีการที่เราจะนำไปใช้ภายใน90ของเรา รุ่น.101รหัส> เป็นวิธีการภายใน OAuth
เพิ่มการย้ายเพื่อแก้ไขโมเดลผู้ใช้
ตอนนี้เราจำเป็นต้องเพิ่มคอลัมน์บางส่วนให้กับโมเดลผู้ใช้ โดยเฉพาะ 110 คอลัมน์และ 123 คอลัมน์:
เรียกใช้ 133 เพื่อจบขั้นตอนนี้
ทำให้ Devise Model Omniauthable
ที่นี่ เราจะต้องแก้ไข 146 ของเรา สร้างโมเดลโดยเพิ่มโมดูล Devise Omniauthable เข้าไป:
หลังจากนั้น ให้เพิ่ม 150 วิธีการ ซึ่งจะถูกเรียกจาก 161 ที่เราเพิ่งตั้งค่า:
ตอนนี้เราเหลืออีกสิ่งหนึ่ง:การเพิ่มลิงก์เข้าสู่ระบบไปยังมุมมอง Devise ของเรา
ตั้งค่าลิงค์เข้าสู่ระบบ
ตามค่าเริ่มต้น Devise จะเพิ่มลิงค์เข้าสู่ระบบของผู้ให้บริการที่เหมาะสมให้กับคุณโดยอัตโนมัติในมุมมองการลงทะเบียนผู้ใช้และการเข้าสู่ระบบ ลิงค์นี้จะใช้ 172 แต่เรารู้ว่า OmniAuth 2.0+ ชอบ 184 คำขอ ดังนั้นเราจึงจำเป็นต้องปิดการใช้งานลิงก์และแทรกลิงก์ของเราเองโดยใช้ 193 คำขอ:
ด้วยเหตุนี้ เราจึงตั้งค่าแอป Ruby on Rails 7 ด้วยการตรวจสอบสิทธิ์ Devise และ GitHub OAuth ได้สำเร็จ คุณสามารถรับซอร์สโค้ดแบบเต็มของแอปที่แสดงร่วมได้ที่นี่
ต่อไป เราจะพูดถึงกรณีการใช้งานขั้นสูงอื่น:การใช้ Devise เพื่อตรวจสอบสิทธิ์การเรียก API
การตรวจสอบสิทธิ์ API ด้วย Devise สำหรับ Ruby
ในปัจจุบัน ไม่ใช่เรื่องแปลกที่ผู้ใช้จะคาดหวังว่าจะสามารถเชื่อมต่อกับแอปของคุณผ่าน API ได้ ในส่วนนี้ เราจะมาดูกันว่าเราจะตรวจสอบคำขอของผู้ใช้ดังกล่าวอย่างปลอดภัยโดยใช้ Devise ได้อย่างไร
ในกรณีที่โดยทั่วไปการตรวจสอบสิทธิ์บนเบราว์เซอร์เป็นแบบใช้คุกกี้ การตรวจสอบสิทธิ์ API ส่วนใหญ่จะเกิดขึ้นผ่านโทเค็นที่เรียกว่า JSON Web Tokens (หรือเพียงแค่ JWT) ซึ่งถูกส่งผ่านไปในส่วนหัว
เคล็ดลับ :สำหรับวัตถุประสงค์ของส่วนนี้ เราจะถือว่าเรากำลังทำงานร่วมกับแอป Rails API เท่านั้น หากต้องการติดตาม ให้สร้างด้วย 209 ป>
ขั้นตอนการตรวจสอบสิทธิ์ที่ใช้ JWT
ดังที่เราได้กล่าวไปแล้ว การรับรองความถูกต้องของ API จะขึ้นอยู่กับโทเค็น JWT และสิ่งสำคัญคือเราต้องเข้าใจว่าขั้นตอนการตรวจสอบความถูกต้องตาม JWT เกิดขึ้นได้อย่างไร โดยพื้นฐานแล้ว จะเป็นไปตามลำดับขั้นตอนทั่วไปตามที่ระบุไว้ด้านล่าง:
- ไคลเอนต์ผู้ใช้ทำการเรียกไปยังแอป API
- แอป API ตอบสนองด้วย JSON Web Token (JWT) ซึ่งเป็นโทเค็นการตรวจสอบสิทธิ์ที่สามารถใช้แทนคุกกี้ได้
- คำขอครั้งต่อไปโดยไคลเอนต์ผู้ใช้ถูกสร้างขึ้นโดยใช้โทเค็นนี้ใน
212ส่วนหัว. - จากนั้นผู้ใช้สามารถกดการดำเนินการ Devise 'ทำลายเซสชัน' ซึ่งส่งผลให้โทเค็นถูกทำลายและผู้ใช้ถูกออกจากระบบ
ตอนนี้ เรามาเริ่มดำเนินการตามขั้นตอนนี้ โดยเริ่มจากสิ่งที่เรียกว่าการแบ่งปันทรัพยากรข้ามต้นทาง (CORS)
การตั้งค่า CORS
CORS ตั้งค่าแอป API ของเราเพื่ออนุญาตคำขอจากแหล่งภายนอก CORS เป็นนโยบายความปลอดภัยบน HTTP ที่กำหนดวิธีที่แอปพลิเคชันของคุณจัดการคำขอภายนอก ตามค่าเริ่มต้น CORS จะบล็อกคำขอใดๆ ที่มาจากโดเมนที่แตกต่างจากโดเมนที่ส่งคำขอครั้งแรก (กล่าวคือ คำขอที่มาจาก "ต้นทาง" อื่น)
เพื่อจัดการ CORS อย่างถูกต้อง เราจะใช้อัญมณีที่ดี 226 . ใน 239 ยกเลิกหมายเหตุบรรทัดด้านล่าง จากนั้นเรียกใช้ 243 :
นอกจากนี้ ให้เปิดไฟล์ตัวเริ่มต้น CORS ที่เกี่ยวข้องและแก้ไขดังต่อไปนี้:
หมายเหตุสำคัญบางประการเกี่ยวกับสิ่งที่เราเพิ่งทำ:
252รหัส> - หมายความว่าแอป API ของเราสามารถรับคำขอจากแหล่งอื่นได้แล้ว260รหัส> - โดยค่าเริ่มต้น276gem จะไม่เปิดเผยการอนุญาตและส่วนหัว UID แต่เราต้องการเนื่องจากเราจะส่งโทเค็นการอนุญาตผ่าน
เมื่อเสร็จแล้ว มาติดตั้ง Devise และ Devise-JWT gem ที่มาพร้อมกัน
เพิ่ม Devise และ Devise-JWT Gems ให้กับแอป Rails ของคุณ
288รหัส> gem เป็นส่วนขยายของ Devise ที่จะช่วยให้เราทำงานกับโทเค็น JWT ได้ เพิ่มอัญมณีไปที่ 298 จากนั้นรัน 308 :
เรียกใช้ตัวสร้างการติดตั้ง Devise 319 .
สร้างและกำหนดค่าโมเดล
เราจำเป็นต้องตั้งค่าสองรุ่น:รุ่นผู้ใช้ Devise ปกติ (326 ) และแบบจำลองที่เราจะใช้สำหรับกลยุทธ์การเพิกถอน (หรืออีกนัยหนึ่งคือ วิธีที่ผู้ใช้จะออกจากระบบ API):
เราแก้ไขโมเดลผู้ใช้ Devise ปกติสำหรับการตรวจสอบสิทธิ์ API โดยการเพิ่มโมดูลที่ตรวจสอบสิทธิ์โทเค็น JWT และกำหนดกลยุทธ์การเพิกถอนโทเค็นเพื่อใช้รุ่นที่สองของเรา 334 :
ต่อไป เรากำหนดค่าโมเดลที่สองของเราโดยอ้างอิงกลยุทธ์การเพิกถอนและตารางการเพิกถอนที่จะใช้:
ในส่วนต่อไปนี้ เราจะสรุปการเพิกถอนโทเค็นและสาเหตุที่เราต้องการ
ความสำคัญของการเพิกถอนโทเค็น
เหตุใดการเพิกถอนโทเค็นจึงมีความสำคัญ เนื่องจากโทเค็น JWT ไม่มีสถานะ เซิร์ฟเวอร์ไม่รู้อะไรเกี่ยวกับพวกเขาเลยนอกจากการลงนาม ในสถานการณ์เช่นนี้ เซิร์ฟเวอร์ไม่มีวิธีที่จะออกจากระบบผู้ใช้โดยการเพิกถอนโทเค็นที่เกี่ยวข้อง เนื่องจากไม่มีทางที่จะเพิกถอนโทเค็นแต่ละรายการได้ เราจึงต้องสร้างโทเค็นขึ้นมาและแจ้งให้เซิร์ฟเวอร์ใช้งาน
เมื่อเพิกถอนโทเค็น สิ่งที่เกิดขึ้นจริงภายใต้ประทุนคือชิ้นส่วนที่มีเอกลักษณ์ของโทเค็น 346 (JWT ID) ถูกแยกออกมาและใช้ตามกลยุทธ์การเพิกถอนที่กำหนดไว้
แน่นอนว่านี่เป็นอีกคำถามหนึ่งว่ากลยุทธ์การเพิกถอนโทเค็นคืออะไร โดยสรุป มันเป็นคำจำกัดความของวิธีที่เซิร์ฟเวอร์ของคุณจัดการการเพิกถอนโทเค็น มีกลยุทธ์การเพิกถอนพื้นฐานสามประการ:
- กลยุทธ์ JTIMatcher - ที่นี่ คอลัมน์เฉพาะที่เรียกว่า "jti" จะถูกเพิ่มให้กับโมเดลผู้ใช้ ซึ่งทำหน้าที่เป็นตารางการเพิกถอนด้วย เมื่อใดก็ตามที่ผู้ใช้ส่งคำขอ
352ในส่วนหัวจะจับคู่กับโทเค็นที่เก็บไว้ และอนุญาตให้เข้าถึงได้เมื่อพบรายการที่ตรงกันเท่านั้น - กลยุทธ์การปฏิเสธ - สำหรับอันนี้คือ
364และการหมดอายุของโทเค็น (374ของโทเค็นที่ถูกเพิกถอน) จะถูกจัดเก็บไว้ในตารางฐานข้อมูล สำหรับทุกคำขอที่ทำโดยผู้ใช้ จะมีการตรวจสอบกับตารางนี้โดยเปรียบเทียบโทเค็นปัจจุบันของผู้ใช้387กับอันที่ถูกเพิกถอนในฐานข้อมูล หากพบการจับคู่ คำขอของผู้ใช้นั้นจะถูกปฏิเสธ - กลยุทธ์รายการที่อนุญาต - ในทางหนึ่ง กลยุทธ์นี้คล้ายกับกลยุทธ์แรก ยกเว้นว่าตารางที่เก็บ JWT IDs อยู่ในความสัมพันธ์แบบหนึ่งต่อกลุ่มกับอีกตารางหนึ่งที่เก็บโทเค็นผู้ใช้ เมื่อใดก็ตามที่มีการร้องขอ
398ของผู้ใช้ ที่จัดเก็บไว้ในตารางรายการที่อนุญาตจะจับคู่กับสิ่งที่จัดเก็บไว้ในตารางที่ตรงกับโทเค็น อนุญาตให้เข้าถึงได้ก็ต่อเมื่อพบรายการที่ตรงกัน
แน่นอนว่านี่เป็นภาพรวมที่เรียบง่ายมากของการเพิกถอนโทเค็น และคุณสามารถเรียนรู้เพิ่มเติมได้ที่นี่
ตั้งค่าคีย์การลงนามสำหรับโทเค็น JWT
เนื่องจากเราจะใช้โทเค็นที่ปลอดภัยในการตรวจสอบสิทธิ์ผู้ใช้และคำขอของพวกเขา เราจึงต้องมีวิธีเซ็นชื่อให้กับพวกเขา นี่คือที่มาของรหัสลับของเรา ขอแนะนำให้คุณสร้างรหัสใหม่ที่แตกต่างจากรหัสลับของ Rails นั่นคือ 408 .
เรียกใช้ 417 เพื่อสร้างคีย์เฉพาะ จากนั้นแก้ไข Devise Initializer เพื่อรวมคีย์นี้:
สุดท้าย มาตั้งค่าคอนโทรลเลอร์กัน
ตั้งค่าคอนโทรลเลอร์
ขั้นตอนสุดท้ายในการใช้งาน Devise สำหรับการตรวจสอบสิทธิ์ API คือการตั้งค่าตัวควบคุมของเรา เพื่อความเรียบง่าย เราจะตั้งค่าตัวควบคุมสองตัว:ตัวหนึ่งสำหรับจัดการการลงทะเบียน และอีกตัวหนึ่งสำหรับเซสชัน
มาสร้างสิ่งเหล่านี้ด้วยตนเอง โดยเริ่มจากตัวควบคุมการลงทะเบียน:
เกิดอะไรขึ้นกับคอนโทรลเลอร์นี้:
- เรากำหนดค่าให้ตอบสนองต่อคำขอด้วย JSON
- เราระบุ
421การดำเนินการที่ส่งคืนผลลัพธ์ของการลงทะเบียนที่สำเร็จหรือล้มเหลว
และตอนนี้สำหรับตัวควบคุมเซสชัน:
เช่นเดียวกับตัวควบคุมการลงทะเบียน ที่นี่เราระบุว่าตัวควบคุมจะตอบสนองด้วย JSON นอกจากนี้เรายังกำหนด 434 การดำเนินการเมื่อผู้ใช้เข้าสู่ระบบสำเร็จและ 443 เพื่อจัดการผู้ใช้ที่ออกจากระบบ
และด้วยเหตุนี้ คุณจึงควรมีขั้นตอนการตรวจสอบสิทธิ์ API ที่ใช้งานได้ ซึ่งขับเคลื่อนโดยโทเค็น Devise และ JWT!
ส่วนสุดท้ายของเราจะดูอย่างรวดเร็วว่าคุณสามารถติดตามการเข้าสู่ระบบของผู้ใช้โดยใช้ Devise และ Authtrail ได้อย่างไร
การติดตามการเข้าสู่ระบบประดิษฐ์ด้วย Authtrail
สมมติว่าคุณต้องการส่งอีเมลแจ้งเตือนผู้ใช้แอปของคุณทุกครั้งที่มีคนลงชื่อเข้าใช้บัญชีของตน โดยมีรายละเอียด เช่น ที่อยู่ IP และการประทับเวลาของการเข้าสู่ระบบ คุณสามารถทำสิ่งนี้ให้สำเร็จได้อย่างไร
คุณจะต้องติดตามการเข้าสู่ระบบของผู้ใช้ จากนั้นใช้ข้อมูลนั้นในอีเมลแจ้งเตือนที่คุณส่งให้ผู้ใช้ของคุณ แต่ก่อนอื่น คุณจะต้องมีวิธีติดตามการเข้าสู่ระบบของผู้ใช้ก่อน ซึ่งสามารถทำได้โดยใช้อัญมณีชั้นดีที่เรียกว่า Authtrail ซึ่งเข้ากันได้ดีกับ Devise เช่นกัน
การติดตั้ง Authtrail
ขั้นตอนแรกคือการติดตั้งอัญมณีด้วย 450 . นอกจากนี้ เนื่องจากคุณจะจัดเก็บข้อมูลที่สามารถระบุตัวผู้ใช้ได้ เช่น อีเมลและที่อยู่ IP ไว้ในฐานข้อมูลแอปของคุณ ขอแนะนำอย่างยิ่งให้คุณเข้ารหัสข้อมูลนี้ในการใช้งานจริงโดยใช้การผสมผสานระหว่าง Lockbox และ Blindindex gems
จากนั้น เรียกใช้ตัวสร้าง Authtrail เพื่อสร้างเครื่องมือเริ่มต้นและการโยกย้ายตารางที่จะจัดเก็บข้อมูลการเข้าสู่ระบบ:
วิธีการทำงานของ Authtrail
เมื่อใดก็ตามที่ผู้ใช้พยายามเข้าสู่ระบบ บันทึก Authtrail ใหม่จะถูกสร้างขึ้นโดยมีรายละเอียดที่สำคัญดังต่อไปนี้:
- ที่อยู่อีเมลสำหรับเข้าสู่ระบบที่ใช้
- ไม่ว่าการเข้าสู่ระบบจะสำเร็จหรือไม่
- สาเหตุที่การเข้าสู่ระบบล้มเหลว (หากการเข้าสู่ระบบล้มเหลว)
- ที่อยู่ IP ของผู้ใช้
466และอีกมากมาย
จากนั้นคุณสามารถใช้ข้อมูลนี้ได้ตามต้องการ ตัวอย่างเช่น คุณสามารถส่งอีเมลแจ้งเตือนไปยังผู้ใช้ รวมถึงอีเมลและข้อมูลที่อยู่ IP เพื่อแจ้งให้พวกเขาทราบว่ามีการพยายามเข้าสู่ระบบในบัญชีของพวกเขา
อ่านเอกสารประกอบของ Authtrail เพื่อดูความเป็นไปได้ทั้งหมดที่คุณสามารถใช้ได้
สรุป
ในซีรีส์นี้ เราได้เจาะลึกเกี่ยวกับ Devise gem
อันดับแรก เราต้องทำความเข้าใจพื้นฐานของ Devise รวมถึงวิธีการทำงานของโมดูล ตัวช่วยเหลือ มุมมอง ตัวควบคุม และเส้นทาง ในส่วนที่สองและส่วนสุดท้ายนี้ เราได้สำรวจวิธีใช้ Devise กับ OAuth, Authtrail และสำหรับการตรวจสอบสิทธิ์ API
หวังว่าซีรีส์นี้จะทำหน้าที่เป็นแนวทางที่เป็นประโยชน์สำหรับทุกสิ่งในการตรวจสอบสิทธิ์ Devise
ขอให้สนุกกับการเขียนโค้ด!
ปล. หากคุณต้องการอ่านโพสต์ Ruby Magic ทันทีที่เผยแพร่ สมัครรับจดหมายข่าว Ruby Magic ของเราและไม่พลาดแม้แต่โพสต์เดียว! ป>