Universally Unique Identifiers (UUIDs) หรือที่รู้จักกันในชื่อ GUIDs มีความสำคัญในการสร้างตัวระบุเฉพาะในแอปพลิเคชันซอฟต์แวร์ต่างๆ UUID เวอร์ชัน 4 มีประโยชน์อย่างยิ่ง เนื่องจากใช้ตัวเลขสุ่มที่ปลอดภัยด้วยการเข้ารหัส ซึ่งรับประกันความเป็นเอกลักษณ์ในระดับสูง บทความนี้นำเสนอคลาส Apex ที่แข็งแกร่ง GuidUtil
พร้อมด้วยคลาสทดสอบ เพื่อสร้างสตริง GUID ได้อย่างมีประสิทธิภาพ ซึ่งเป็นไปตามมาตรฐาน UUID เวอร์ชัน 4 ภายในสภาพแวดล้อม Salesforce
หลายวิธีในการสร้าง GUID อาจไม่เพียงพอ โดยอาจไม่ได้ใช้ตัวสร้างตัวเลขสุ่มที่ปลอดภัยด้วยการเข้ารหัส หรือไม่ปฏิบัติตามข้อกำหนดของ UUID v4 อย่างครบถ้วน คลาส GuidUtil
แก้ไขข้อบกพร่องเหล่านี้ โดยนำเสนอวิธีการที่เชื่อถือได้สำหรับนักพัฒนาที่ต้องการ สร้างค่า GUID ใน Apex
/* วิธีสร้าง GUID เวอร์ชัน 4 (สุ่ม) 1. สร้างบิตสุ่ม 128 บิต 2. ตั้งค่าเวอร์ชัน: นำไบต์ที่ 7 มาดำเนินการ AND กับ 0x0f ตามด้วยการดำเนินการ OR ของ 0x40 3. ตั้งค่าตัวแปร: นำไบต์ที่ 9 มาดำเนินการ AND กับ 0x3f ตามด้วยการดำเนินการ OR ของ 0x80 4. แปลงข้อมูลเป็นเลขฐานสิบหกและเพิ่มเครื่องหมายขีด */ public class GuidUtil { static List<String> hexMap = new List<String> { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; public static String NewGuid() { String randomStringAsHex = EncodingUtil.ConvertTohex(Crypto.GenerateAESKey(128)); String versionHexBits = randomStringAsHex.SubString(14,16); // บิตที่ 7 String variantHexBits = randomStringAsHex.SubString(18,20); // บิตที่ 9 Integer versionIntBits = convertHexToInt(versionHexBits); Integer variantIntBits = convertHexToInt(variantHexBits); Integer versionShiftedIntBits = versionIntBits & 15 | 64; // (i & 0x0f) | 0x40 Integer variantShiftedIntBits = variantIntBits & 63 | 128; // (i & 0x3f) | 0x80 String versionShiftedHexBits = convertIntToHex(versionShiftedIntBits); // เริ่มต้นด้วย 4 เสมอ String variantShiftedHexBits = convertIntToHex(variantShiftedIntBits); // เริ่มต้นด้วย 8,9,a,b เสมอ String guid = randomStringAsHex.SubString(0,8) + '-' + randomStringAsHex.SubString(8,12) + '-' + versionShiftedHexBits + randomStringAsHex.SubString(14,16) + '-' + variantShiftedHexBits + randomStringAsHex.SubString(18,20) + '-' + randomStringAsHex.substring(20); return guid; } static Integer convertHexToInt(String hex) { Integer d0 = hexMap.IndexOf(hex.Substring(1,2)); Integer d1 = hexMap.IndexOf(hex.Substring(0,1)); Integer intval = d0 + (d1*16); return intval; } static String convertIntToHex(Integer intval) { // https://stackoverflow.com/a/13465128 String hs0 = hexMap.Get(intval & 15); // i & 0x0f String hs1 = hexMap.Get(((intval >> 4) & 15)); //(i >> 4) & 0x0f return hs1+hs0; } }
คลาส GuidUtil
นี้นำเสนอเมธอด NewGuid()
ซึ่งเป็นฟังก์ชันหลักในการ สร้าง GUID ลองมาดูวิธีการทำงานทีละขั้นตอน ซึ่งสอดคล้องกับกระบวนการสร้าง UUID v4:
- สร้างบิตสุ่ม 128 บิต: กระบวนการเริ่มต้นด้วยการสร้างข้อมูลสุ่มที่ปลอดภัยด้วยการเข้ารหัส 128 บิตโดยใช้
Crypto.GenerateAESKey(128)
ซึ่งรับประกันความไม่สามารถคาดเดาได้ในระดับสูง ซึ่งเป็นหลักสำคัญของ UUID v4 จากนั้นข้อมูลสุ่มนี้จะถูกแปลงเป็นตัวแทนสตริงเลขฐานสิบหกโดยใช้EncodingUtil.ConvertTohex()
- ตั้งค่าเวอร์ชัน: เพื่อให้ UUID สอดคล้องกับเวอร์ชัน 4 บิตเฉพาะต้องระบุเวอร์ชัน รหัสจะแยกไบต์ที่ 7 (อักขระ 14-16 ในสตริงเลขฐานสิบหก) และดำเนินการ AND ระดับบิตกับ
0x0f
ตามด้วยการดำเนินการ OR ระดับบิตกับ0x40
การดำเนินการนี้จะตั้งค่าบิตเวอร์ชันเป็น ‘0100’ ซึ่งเป็นรูปแบบที่กำหนดไว้สำหรับ UUID เวอร์ชัน 4 - ตั้งค่าตัวแปร: เช่นเดียวกับเวอร์ชัน ฟิลด์ตัวแปรก็ต้องการการตั้งค่าบิตเฉพาะเช่นกัน ไบต์ที่ 9 (อักขระ 18-20 ในสตริงเลขฐานสิบหก) จะถูกแยกออกมา และดำเนินการ AND ระดับบิตกับ
0x3f
และ OR ระดับบิตที่ตามมาด้วย0x80
จะถูกดำเนินการ ซึ่งจะตั้งค่าบิตตัวแปรเป็น ’10xx’ ตามที่กำหนดไว้สำหรับตัวแปร UUID ที่พบบ่อยที่สุด (ตัวแปร 1 หรือที่เรียกว่าตัวแปร Leach-Salz) - แปลงเป็นเลขฐานสิบหกและเพิ่มเครื่องหมายขีด: ขั้นตอนสุดท้ายเกี่ยวข้องกับการประกอบสตริง GUID ในรูปแบบ UUID มาตรฐาน รหัสจะนำสตริงย่อยจากสตริงเลขฐานสิบหกแบบสุ่ม โดยรวมบิตเลขฐานสิบหกของเวอร์ชันและตัวแปรที่แก้ไขแล้ว และแทรกเครื่องหมายยัติภังค์ที่ตำแหน่งเดิม เพื่อสร้างสตริง UUID ในรูปแบบ “xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx” โดยที่ ‘y’ ถูกกำหนดโดยบิตตัวแปร
เมธอดตัวช่วยที่สนับสนุน convertHexToInt(String hex)
และ convertIntToHex(Integer intval)
อำนวยความสะดวกในการจัดการบิตโดยการแปลงระหว่างการแทนค่าสตริงเลขฐานสิบหกและค่าจำนวนเต็มตามที่จำเป็นสำหรับการตั้งค่าบิตเวอร์ชันและตัวแปร
เพื่อให้แน่ใจว่าคลาส GuidUtil
สร้างค่า GUID ที่ถูกต้องตรงตามมาตรฐาน UUID เวอร์ชัน 4 จึงมีคลาสทดสอบ GuidUtilSpec
ให้
@isTest public class GuidUtilSpec { private static testmethod void GuidIsV4() { Pattern p = Pattern.compile('[w]{8}-[w]{4}-4[w]{3}-[89ab][w]{3}-[w]{12}'); for(Integer x = 0; x < 100; x++) { Matcher m = p.matcher(GuidUtil.NewGuid()); System.assert(m.matches() == true); } } }
เมธอดทดสอบ GuidIsV4()
ใช้นิพจน์ทั่วไป [w]{8}-[w]{4}-4[w]{3}-[89ab][w]{3}-[w]{12}
เพื่อตรวจสอบความถูกต้องของรูปแบบของสตริง GUID ที่สร้างขึ้น regex นี้ตรวจสอบเฉพาะ:
- การมีอยู่ของเครื่องหมายยัติภังค์ในตำแหน่งที่ถูกต้อง
- อักขระเวอร์ชันคือ ‘4’ (บังคับใช้โดย
-4[w]{3}-
) - อักขระตัวแปรเป็นหนึ่งใน ‘8’, ‘9’, ‘a’ หรือ ‘b’ (บังคับใช้โดย
-[89ab][w]{3}-
)
การทดสอบจะวนซ้ำ 100 ครั้ง โดยสร้าง GUID ใหม่ในแต่ละการวนซ้ำและยืนยันว่าตรงกับรูปแบบ UUID v4 ซึ่งเป็นการตรวจสอบทางสถิติอย่างมีนัยสำคัญว่าคลาส GuidUtil
สร้างสตริง GUID ที่สอดคล้องกับมาตรฐานเวอร์ชัน 4 ได้อย่างน่าเชื่อถือ
โดยสรุป คลาส GuidUtil
และการทดสอบประกอบนำเสนอโซลูชันที่สมบูรณ์และผ่านการตรวจสอบแล้วสำหรับนักพัฒนาที่ต้องการ สร้างค่า GUID ภายในรหัส Apex โดยการใช้ประโยชน์จากการสร้างตัวเลขสุ่มที่ปลอดภัยด้วยการเข้ารหัสและปฏิบัติตามข้อกำหนดของ UUID เวอร์ชัน 4 อย่างพิถีพิถัน รหัสนี้ทำให้มั่นใจได้ว่าการสร้างตัวระบุเฉพาะและเป็นไปตามมาตรฐานสำหรับข้อกำหนดของแอปพลิเคชันต่างๆ ใน Salesforce