Security & Privacy
แนะนำวิธีทำให้แอปพลิเคชันปลอดภัยใน Parse ด้วย Back4app
19 นาที
วิธีการสร้างแอปที่ปลอดภัยโดยใช้ parse บทนำ สวัสดีชุมชน back4app! นี่คือบทเรียนจากแขกรับเชิญ joren winge ที่ startup soul http //startup soul com/ เราช่วยสตาร์ทอัพในการสร้างและเปิดตัวผลิตภัณฑ์ของพวกเขาอย่างรวดเร็ว เพื่อนของเราที่ back4app ขอให้เราสอนคุณวิธีการสร้างแอปที่ปลอดภัยบน back4app ในโพสต์นี้ เราจะพาคุณไปผ่านขั้นตอนในการสร้างแอป to do ที่ปลอดภัยบน back4app ความปลอดภัยเป็นสิ่งสำคัญ หากแอปของคุณประสบความสำเร็จ คุณจะต้องมั่นใจว่าข้อมูลของแอปของคุณปลอดภัยและระบบของคุณไม่สามารถถูกแฮ็กได้ ฟีเจอร์ด้านความปลอดภัยบน parse มาพูดถึงระดับความปลอดภัยแรกกันก่อน acls (รายการควบคุมการเข้าถึง) acls เป็นเพียงกฎที่คุณตั้งเมื่อคุณสร้างวัตถุ สมมติว่าคุณสร้างรายการที่ต้องทำ ในขณะสร้างคุณสามารถบอกได้ว่าวัตถุสามารถอ่านได้โดยใคร และใครสามารถเขียนได้ คุณสามารถกำหนดผู้ใช้บางคนให้สามารถอ่านวัตถุหรือเขียนไปยังวัตถุได้ หรือคุณสามารถตั้งค่าหนึ่งในนั้นให้เป็นสาธารณะซึ่งอนุญาตให้เข้าถึงได้โดยใครก็ได้ แต่ acls ไม่ทำงานเสมอไป มีบางกรณีที่คุณอาจต้องการมีตรรกะที่ซับซ้อนมากขึ้นแทนที่จะเป็น acl ที่ง่าย บางครั้งคุณอาจจะติดอยู่ในมุมที่คุณอาจต้องให้ใครบางคนเข้าถึงวัตถุในเงื่อนไขแทนที่จะเป็นแบบสัมบูรณ์เหมือนกับ acls ดังนั้นเรามาข้ามการใช้ acls กันเถอะ พวกมันแข็งเกินไปและในขณะเดียวกันก็อนุญาตให้เข้าถึงข้อมูลมากเกินไป ดังนั้นฉันจะบอกความลับในการสร้างแอปที่ปลอดภัยบน back4app และ parse server คุณพร้อมหรือยัง? การอนุญาตระดับคลาส! ใช่ เราจะตั้งการอนุญาตระดับคลาสสำหรับแต่ละตารางในฐานข้อมูลของเรา และระดับการอนุญาตที่เราจะตั้งคือไม่มีการอนุญาตเลย เราจะล็อคตารางทุกตารางเพื่อไม่ให้มีการเข้าถึงการอ่านหรือเขียนโดยใครเลย! ฟังดูรุนแรง ฉันรู้ แต่เป็นขั้นตอนแรกในการสร้างแอปที่ปลอดภัย การอนุญาตเพียงอย่างเดียวที่เราจะอนุญาตคือในตารางผู้ใช้ซึ่งจะใช้สำหรับการสร้างวัตถุผู้ใช้ใหม่และให้ผู้ใช้ดูข้อมูลของตนเองซึ่งจำเป็นสำหรับการรีเฟรชผู้ใช้ปัจจุบัน เราจะป้องกันผู้ใช้ไม่ให้สามารถดูข้อมูลของผู้ใช้อื่นโดยการใช้ acls นี่คือครั้งเดียวที่เราจะใช้ acls ดังนั้นฉันคิดว่าพวกมันไม่ได้ไร้ประโยชน์ทั้งหมด พวกมันดีที่จะมี แต่ไม่ต้องพึ่งพาพวกมันในการทำทุกอย่าง แต่เราจะเข้าถึงข้อมูลได้อย่างไรคุณถาม? คำถามดี ดีใจที่คุณคิดเกี่ยวกับมัน! ความลับในการให้ลูกค้าสามารถเข้าถึงข้อมูลในลักษณะที่ควบคุมได้คือการทำให้การโต้ตอบแต่ละครั้งระหว่างลูกค้าและฐานข้อมูลถูกกรองผ่านฟังก์ชันโค้ดคลาวด์ ใช่ ทุกครั้งที่คุณทำอะไรกับแอปของคุณมันจะผ่านฟังก์ชันโค้ดคลาวด์ที่กำหนดเอง ไม่ต้องใช้ pfqueries ที่อิงจากลูกค้าอีกต่อไป คุณแทบจะข้ามการใช้ parse sdk ที่อิงจากลูกค้าทั้งหมด ยกเว้นฟังก์ชันการลงทะเบียน ฟังก์ชันการเข้าสู่ระบบ ฟังก์ชันการลืมรหัสผ่าน และฟังก์ชันการออกจากระบบ สำหรับสิ่งเหล่านี้ เราจะยังคงใช้ sdk ของลูกค้าแบบเนทีฟ มันง่ายกว่า คุณเคยเขียนโค้ดคลาวด์มาก่อนหรือไม่? ไม่ คุณพูด? อืม มันง่ายมาก มันเป็นเพียง javascript และใช้ parse javascript sdk แต่ภายในเซิร์ฟเวอร์ของแอปของคุณเอง ในความเป็นจริง เนื่องจาก parse server อิงจาก node js มันจึงคล้ายกับการเขียนเส้นทางด้วย express แต่ยังง่ายกว่าเพราะภาษาคิวรีของคุณถูกติดตั้งไว้แล้วและฟังก์ชันโค้ดคลาวด์เขียนได้ง่ายกว่าการสร้างแอป node js express ทั้งหมด ดังนั้นนี่คือสิ่งที่เราจะทำ เราจะใช้แอป todo สำหรับ ios ที่ฉันได้สร้างขึ้นแล้ว เราจะไม่ยุ่งกับการแสดงให้คุณเห็นว่าฉันสร้างมันขึ้นมาอย่างไร แทนที่จะมุ่งเน้นไปที่การเขียนโค้ดคลาวด์และการรักษาความปลอดภัยของฐานข้อมูล แอป todo จะเป็นแอปที่ปลอดภัยซึ่งคุณสามารถเข้าถึง todo ของคุณเองได้เท่านั้นและคุณสามารถเขียน todo ของคุณเองได้เท่านั้น ข้อมูลจะปลอดภัยบนเซิร์ฟเวอร์ห่างไกลจากลูกค้าที่เป็นอันตราย ฉันจะแสดงให้คุณเห็นวิธีการเขียนงานพื้นหลังที่ปลอดภัยของ parse โดยพื้นฐานแล้วเหมือนกับงาน cron เพื่อให้คุณสามารถมีบริการอัตโนมัติส่งและจัดการข้อมูลของคุณตามกำหนดเวลา ฟังดูซับซ้อนแต่ไม่ใช่ แค่จินตนาการถึงหุ่นยนต์เซิร์ฟเวอร์ตัวเล็ก ๆ ที่ทำทุกอย่างที่คุณต้องการตามกำหนดเวลาอัตโนมัติ ฟังดูเจ๋งใช่ไหม? โอเค ดังนั้นเรามาเริ่มกันเถอะ!!!!!! มาจัดตั้งแอป todo ที่ปลอดภัย back4app กันเถอะ 1\) สร้างแอปบน back4app สร้างแอปใหม่บน back4app ตั้งชื่อแอปว่า ‘secure todo app’ หมายเหตุ ติดตาม บทแนะนำการสร้างแอปใหม่ parse เพื่อเรียนรู้วิธีการสร้างแอปที่ back4app ไปที่หน้าการตั้งค่าหลักของแอปแล้วคลิกที่ แก้ไขรายละเอียดแอป ปิดการใช้งานช่องทำเครื่องหมายที่เรียกว่า ‘อนุญาตให้สร้างคลาสของลูกค้า’ เพื่อปิดการสร้างคลาสของลูกค้าและกดบันทึก เราต้องการจำกัดสิ่งที่ลูกค้าสามารถทำได้ตามกฎ 2\) ตั้งค่าการอนุญาตความปลอดภัยระดับคลาสสำหรับคลาสผู้ใช้ ถัดไปเราจะตั้งค่าการอนุญาตสำหรับคลาสผู้ใช้ ไปที่แดชบอร์ดฐานข้อมูล back4app และคลิกที่คลาสผู้ใช้ จากนั้นคลิกที่แท็บความปลอดภัย แล้วคลิกที่ไอคอนเกียร์ที่มุมขวาบน คุณควรเห็นเมนูที่เขียนว่า ง่าย/ขั้นสูง เลื่อนสไลเดอร์ไปที่ขั้นสูง คุณควรเห็นการอนุญาตระดับคลาสทั้งหมดสำหรับคลาสนี้ ปิดการเลือกช่อง find ปิดการเลือกช่อง update และ delete สุดท้ายปิดการเลือกช่อง add field จากนั้นกดบันทึก การตั้งค่าความปลอดภัยของคุณควรมีลักษณะดังนี้ 3\) สร้างคลาส todo กดสร้างคลาสและตั้งชื่อว่า todo ตั้งค่าประเภทคลาสเป็นแบบกำหนดเอง 4\) ตั้งค่าการอนุญาตระดับคลาสสำหรับคลาส todo ถัดไปเราจะตั้งค่าการอนุญาตสำหรับคลาส todo ไปที่แดชบอร์ดฐานข้อมูล back4app และคลิกที่คลาส todo จากนั้นคลิกที่แท็บความปลอดภัย แล้วคลิกที่ไอคอนเกียร์ที่มุมขวาบน คุณควรเห็นเมนูที่เขียนว่า ง่าย/ขั้นสูง เลื่อนสไลเดอร์ไปที่ขั้นสูง คุณควรเห็นการอนุญาตระดับคลาสทั้งหมดสำหรับคลาสนี้ ปิดทุกอย่างแล้วกดบันทึก การตั้งค่าความปลอดภัยของคุณควรมีลักษณะดังนี้ 5\) มาลองเพิ่มคอลัมน์บางส่วนในคลาส todo ก่อนอื่นให้เรารวมคลาส todo กับคลาส user เราจะทำโดยการเพิ่ม 2 คอลัมน์ คอลัมน์แรกจะถูกเรียกว่า ‘user’ และจะเป็นตัวชี้กลับไปที่คลาสผู้ใช้ ถัดไปให้เราสร้างคอลัมน์สำหรับ id ของวัตถุผู้ใช้ที่สร้างมันขึ้นมา มันจะเป็นประเภทสตริงและจะถูกเรียกว่า ‘userobjectid’ ถัดไปให้เราสร้างคอลัมน์เพื่อเก็บข้อมูล todo ที่แท้จริงของเรา มันจะเป็นประเภทสตริงและจะถูกเรียกว่า ‘tododescription’ ให้เราสร้าง boolean เพื่อเก็บสถานะของ todo ให้เราตั้งชื่อมันว่า ‘finished’ สุดท้ายให้เรากเพิ่มอีกหนึ่งคอลัมน์เพื่อเก็บวันที่ที่คุณเสร็จสิ้น todo ของคุณ ให้เราตั้งชื่อมันว่า ‘finisheddate’ และตั้งเป็นประเภทวันที่ คลาส todo ของคุณควรมีลักษณะดังนี้ 6\) มาดูที่ลูกค้ากัน ลูกค้าเป็นแอป todo ที่ค่อนข้างพื้นฐาน มันใช้ฟังก์ชัน parse ที่สร้างขึ้นมาเพื่อเข้าสู่ระบบ สร้างผู้ใช้ใหม่ และรีเซ็ตรหัสผ่านของคุณ นอกจากนี้ทุกอย่างยังเป็นโค้ดคลาวด์ที่มีความปลอดภัย acl ของผู้ใช้จะถูกตั้งค่าเมื่อพวกเขาเข้าสู่ระบบหรือสมัครสมาชิกเพื่อให้แน่ใจว่าระบบมีความปลอดภัย 100% ให้เรเริ่มต้นโดยการเขียนฟังก์ชันโค้ดคลาวด์เพื่อตั้งค่า acl ของผู้ใช้เมื่อเข้าสู่ระบบหรือสมัครสมาชิก ในทุกช่วงเวลา คุณสามารถเข้าถึงโปรเจกต์ ios ที่สร้างขึ้นด้วยบทเรียนนี้ได้ที่ ที่เก็บ github คุณยังสามารถเข้าถึงไฟล์โค้ดคลาวด์ main js ที่สร้างขึ้นสำหรับบทเรียนนี้ได้ที่ ที่เก็บ github 1 ในไคลเอนต์ให้ไปที่ todocontroller swift และมองหาฟังก์ชัน setusersaclsnow ฟังก์ชันนี้จะถูกเรียกเมื่อคุณเข้าสู่ระบบหรือดู loggedinviewcontroller swift ฟังก์ชันจะตรวจสอบว่าคุณได้เข้าสู่ระบบหรือไม่ และถ้าคุณได้เข้าสู่ระบบ มันจะเรียกฟังก์ชันคลาวด์เพื่อตั้งค่า acl ของผู้ใช้ส่วนตัวของคุณ todocontroller swift 1 func setusersaclsnow(){ 2 if pfuser current() != nil{ 3 let cloudparams \[anyhashable\ string] = \["test" "test"] 4 pfcloud callfunction(inbackground setusersacls, withparameters cloudparams, block { 5 (result any?, error error?) > void in 6 if error != nil { 7 //print(error debugdescription) 8 if let descrip = error? localizeddescription{ 9 print(descrip) 10 } 11 }else{ 12 print(result as! string) 13 } 14 }) 15 } 16 } 2 ตอนนี้เรามาเขียนฟังก์ชันโค้ดคลาวด์กันเถอะ parse server 3 x 1 parse cloud define('setusersacls', async(request) => { 2 let currentuser = request user; 3 currentuser setacl(new parse acl(currentuser)); 4 return await currentuser save(null, { usemasterkey true }); 5 }); parse server 2 x 1 parse cloud define('setusersacls', function (request, response) { 2 var currentuser = request user; 3 currentuser setacl(new parse acl(currentuser)); 4 currentuser save(null, { 5 usemasterkey true, 6 success function (object) { 7 response success("acls updated"); 8 }, 9 error function (object, error) { 10 response error("got an error " + error code + " " + error description); 11 } 12 }); 13 }); 3 โค้ดคลาวด์นี้ใช้ฟีเจอร์สำคัญสองอย่างในการทำให้แอปของคุณปลอดภัย คือ request user และ masterkey request user ช่วยให้คุณเข้าถึงผู้ใช้ที่ทำการเรียกโค้ดคลาวด์และอนุญาตให้คุณจำกัดการเข้าถึงสำหรับผู้ใช้นั้น ในกรณีนี้ เรากำลังใช้มันเพื่อตั้งค่า acl ของผู้ใช้เพื่อจำกัดการเข้าถึงข้อมูลเฉพาะสำหรับผู้ใช้ปัจจุบันเท่านั้น ด้วยวิธีนี้ผู้ใช้เท่านั้นที่สามารถอ่านข้อมูลของตนเองได้ สิทธิ์ระดับคลาสจะป้องกันไม่ให้มีการเขียนแม้แต่สำหรับผู้ใช้ปัจจุบัน ด้วยวิธีนี้ผู้ใช้ไม่สามารถแก้ไขข้อมูลของตนเองได้ พวกเขาสามารถเปลี่ยนแปลงสิ่งต่าง ๆ เกี่ยวกับผู้ใช้ของตนเองได้ผ่านโค้ดคลาวด์เท่านั้น เป็นไปได้ที่จะนำเข้าข้อมูลเท็จเมื่อผู้ใช้ลงทะเบียนครั้งแรก แต่ฉะแนะนำให้เขียนฟังก์ชันโค้ดคลาวด์เพื่อตรวจสอบข้อมูลของผู้ใช้หลังจากที่ผู้ใช้ใหม่ถูกสร้างขึ้น ฟังก์ชัน parse ที่สร้างผู้ใช้ใหม่ในตัวนั้นมีประโยชน์มาก ดังนั้นฉันคิดว่ามันเป็นการแลกเปลี่ยนที่ดี แต่คุณสามารถตั้งค่าค่าพื้นฐานสำหรับผู้ใช้ผ่านโค้ดคลาวด์ได้ทันทีหลังจากที่พวกเขาลงทะเบียน มีระบบป้องกันหลายอย่างที่คุณสามารถเขียนลงในโค้ดคลาวด์และให้มันทำงานโดยอัตโนมัติและต่อเนื่องโดยใช้งานเบื้องหลังเพื่อตรวจจับข้อมูลผู้ใช้ที่เป็นอันตรายที่ถูกนำเข้ามาเมื่อผู้ใช้ถูกสร้างขึ้นครั้งแรก หากคุณต้องการให้ปลอดภัยจริง ๆ คุณสามารถเก็บข้อมูลที่ละเอียดอ่อนเช่นสถานะสมาชิกหรือข้อมูลการชำระเงินในตารางแยกจากตารางผู้ใช้ ด้วยวิธีนี้ผู้ใช้ไม่สามารถปลอมแปลงข้อมูลที่ละเอียดอ่อนใด ๆ ในการสร้างผู้ใช้ได้ 4 ต่อไปเรามาดูการสร้าง todo กัน ในไคลเอนต์ให้ไปที่ todocontroller swift และมองหาฟังก์ชัน savetodo ฟังก์ชันนี้จะถูกเรียกเมื่อคุณสร้าง todo ใหม่ ฟังก์ชันนี้รับสตริงที่อธิบายถึง todo และบันทึกลงในฐานข้อมูล todocontroller swift 1 func savetodo(todostring\ string, completion @escaping ( result bool, message\ string, todoarray \[todo]) >()){ 2 var resulttodoarray \[todo] = \[] 3 let cloudparams \[anyhashable\ any] = \["todostring"\ todostring] 4 pfcloud callfunction(inbackground createtodosforuser, withparameters cloudparams, block { 5 (result any?, error error?) > void in 6 if error != nil { 7 if let descrip = error? localizeddescription{ 8 completion(false, descrip, resulttodoarray) 9 } 10 }else{ 11 resulttodoarray = result as! \[todo] 12 completion(true, "success", resulttodoarray) 13 } 14 }) 15 } 5 ตอนนี้เรามาเขียนฟังก์ชันโค้ดคลาวด์เพื่อบันทึก todo ลงในฐานข้อมูลกัน parse server 3 x 1 parse cloud define("createtodosforuser", async(request) => { 2 let currentuser = request user; 3 let todostring = request params todostring; 4 let todo = parse object extend("todo"); 5 let todo = new todo(); 6 todo set("user", currentuser); 7 todo set("userobjectid", currentuser id); 8 todo set("tododescription", todostring); 9 todo set("finished", false); 10 return await todo save(null, { usemasterkey true }); 11 }); parse server 2 x 1 parse cloud define("createtodosforuser", function(request, response) { 2 var currentuser = request user; 3 var todostring = request params todostring; 4 var todo = parse object extend("todo"); 5 var todo = new todo(); 6 todo set("user", currentuser); 7 todo set("userobjectid", currentuser id); 8 todo set("tododescription", todostring); 9 todo set("finished", false); 10 todo save(null, { 11 usemasterkey true, 12 success function (object) { 13 response success(\[todo]); 14 }, 15 error function (object, error) { 16 response error("got an error " + error code + " " + error description); 17 } 18 }); 19 }); 6 ฟังก์ชันโค้ดคลาวด์นี้สร้างวัตถุ todo และตั้งค่าผู้ใช้ปัจจุบันเป็นเจ้าของวัตถุ นี่เป็นสิ่งสำคัญเพื่อให้เฉพาะผู้ใช้ที่สร้างมันขึ้นมาสามารถค้นหาหรือแก้ไขได้ โดยการไม่อนุญาตให้สร้าง todos ในไคลเอนต์ เรากำลังบังคับให้วัตถุ todo ปฏิบัติตามมาตรฐานของเราและทำให้แน่ใจว่า todos เป็นของผู้ใช้ที่สร้างมันขึ้นมา 7 ต่อไปเรามาดูการดึง todos ที่คุณสร้างจากเซิร์ฟเวอร์ ในไคลเอนต์ให้ไปที่ todocontroller swift และมองหาฟังก์ชัน gettodosfordate ฟังก์ชันนี้จะถูกเรียกเมื่อคุณดึง todos ของคุณ ฟังก์ชันนี้รับวันที่เป็นพารามิเตอร์และใช้มันเพื่อดึงรายการ todos ที่ถูกสร้างโดยคุณก่อนวันที่นั้นในลำดับที่ลดลง การใช้วันที่เป็นวิธีที่ดีในการเขียนคำสั่ง lazy loading ที่ไม่ใช้ skips skip บางครั้งอาจล้มเหลวในชุดข้อมูลขนาดใหญ่ todocontroller swift 1 func savetodo(todostring\ string, completion @escaping ( result bool, message\ string, todoarray \[todo]) >()){ 2 var resulttodoarray \[todo] = \[] 3 let cloudparams \[anyhashable\ any] = \["date"\ date] 4 pfcloud callfunction(inbackground gettodosforuser, withparameters cloudparams, block { 5 (result any?, error error?) > void in 6 if error != nil { 7 if let descrip = error? localizeddescription{ 8 completion(false, descrip, resulttodoarray) 9 } 10 }else{ 11 resulttodoarray = result as! \[todo] 12 completion(true, "success", resulttodoarray) 13 } 14 }) 15 } 8 ตอนนี้เรามาเขียนฟังก์ชันโค้ดคลาวด์เพื่อดึง todos จากฐานข้อมูลตามวันที่เริ่มต้น เราจะค้นหา todos ที่ถูกสร้างก่อนวันที่พารามิเตอร์ ดังนั้นเราจึงใช้ ‘query lessthan’ เพราะวันที่เป็นตัวเลขที่ใหญ่ขึ้นเมื่อคุณอยู่ในอนาคตมากขึ้น ฉันยังรวมโค้ดที่ยุ่งยากไว้ที่นี่ สมมติว่าเรารวมวัตถุผู้ใช้ที่สร้าง todo แต่เราไม่ต้องการแชร์ข้อมูลที่ละเอียดอ่อนเกี่ยวกับผู้ใช้นั้นกับผู้ใช้อื่น เราจำเป็นต้องลบออกจากการตอบกลับ json ดังนั้นเราจึงมีลูป for ที่เรานำวัตถุผู้ใช้ออกจาก todo ลบอีเมลและชื่อผู้ใช้จาก json และจากนั้นใส่กลับเข้าไปใน todo นี่เป็นประโยชน์ในการลบข้อมูลที่ละเอียดอ่อนจากการเรียก api ในสถานการณ์ที่คุณไม่สามารถควบคุมฟิลด์ที่คุณส่งคืน เช่นวัตถุผู้ใช้ที่รวมอยู่ ในกรณีนี้เราไม่จำเป็นต้องใช้มันจริงๆ เพราะฟังก์ชันนี้จะส่งคืนเฉพาะ todos ที่คุณสร้างเอง เราทำเช่นนี้โดยใช้ currentuser อีกครั้งเพื่อค้นหาเฉพาะ todos ที่สร้างโดย currentuser ที่แนบมากับคำขอ ผลลัพธ์จะถูกส่งคืนในลำดับที่ลดลงเพื่อให้ todos ล่าสุดปรากฏขึ้นก่อน เมื่อคุณต้องการโหลดชุด todos อื่นคุณจะนำวันที่ createdat จาก todo ล่าสุดและใช้เป็นพารามิเตอร์วันที่สำหรับคำขอถัดไป parse server 3 x 1 parse cloud define("gettodosforuser", async(request) => { 2 let currentuser = request user; 3 let date = request params date; 4 let query = new parse query("todo"); 5 query equalto("user", currentuser); 6 query lessthan("createdat", date); 7 query descending("createdat"); 8 query limit(100); 9 query include("user"); 10 let results = await query find({ usemasterkey true }); 11 if(results length === 0) throw new error('no results found!'); 12 13 let resultsarray = \[]; 14 for (let i = 0; i < results length; i++) { 15 let todo = results\[i]; 16 let tempuser = todo get("user"); 17 let jsonuser = tempuser tojson(); 18 delete jsonuser email; 19 delete jsonuser username; 20 21 jsonuser type = "object"; 22 jsonuser classname = " user"; 23 24 let cleanedtodo = todo tojson(); 25 cleanedtodo user = jsonuser; 26 cleanedtodo type = "object"; 27 cleanedtodo classname = "todo"; 28 resultsarray push(cleanedtodo); 29 } 30 return resultsarray; 31 }); parse server 2 x 1 parse cloud define("gettodosforuser", function(request, response) { 2 var currentuser = request user; 3 var date = request params date; 4 var query = new parse query("todo"); 5 query equalto("user", currentuser); 6 query lessthan("createdat", date); 7 query descending("createdat"); 8 query limit(100); 9 query include("user"); 10 query find({ 11 usemasterkey true, 12 success function (results) { 13 var resultsarray = \[]; 14 for (var i = 0; i < results length; i++) { 15 var todo = results\[i]; 16 var tempuser = todo get("user"); 17 var jsonuser = tempuser tojson(); 18 delete jsonuser email; 19 delete jsonuser username; 20 21 jsonuser type = "object"; 22 jsonuser classname = " user"; 23 24 var cleanedtodo = todo tojson(); 25 cleanedtodo user = jsonuser; 26 cleanedtodo type = "object"; 27 cleanedtodo classname = "todo"; 28 resultsarray push(cleanedtodo); 29 } 30 response success(resultsarray); 31 }, 32 error function (error) { 33 response error(" error " + error code + " " + error message); 34 } 35 }); 36 }); 9 ตอนนี้เรามี todos แล้วเราสามารถดูพวกมันในแอปและทำเครื่องหมายว่าทำเสร็จแล้วถ้าเราต้องการ มาทำความเข้าใจในส่วนนี้กันต่อ 10 เพื่อทำเครื่องหมายว่า todo เสร็จสมบูรณ์เพียงแค่กดปุ่ม ‘ทำเครื่องหมายว่าเสร็จสมบูรณ์’ บน todo ใด ๆ ที่คุณสร้างขึ้น สิ่งนี้จะเรียกใช้วิธีการใน todocontroller swift ที่เรียกว่า ‘marktodosascompletedfor’ ซึ่งใช้ todo ที่คุณเลือกเป็นพารามิเตอร์ มันจะส่ง todo objectid ไปยังเซิร์ฟเวอร์เป็นพารามิเตอร์และจากนั้นส่งคืน todo ที่อัปเดตเป็นผลลัพธ์ todocontroller swift 1 func marktodosascompletedfor(todo\ todo, completion @escaping ( result bool, message\ string, todoarray \[todo]) >()){ 2 var resulttodoarray \[todo] = \[] 3 let cloudparams \[anyhashable\ any] = \["todoid"\ todo objectid ?? ""] 4 pfcloud callfunction(inbackground marktodoascompletedforuser, withparameters cloudparams, block { 5 (result any?, error error?) > void in 6 if error != nil { 7 if let descrip = error? localizeddescription{ 8 completion(false, descrip, resulttodoarray) 9 } 10 }else{ 11 resulttodoarray = result as! \[todo] 12 completion(true, "success", resulttodoarray) 13 } 14 }) 15 } 11 ตอนนี้เราจะเขียนโค้ดคลาวด์เพื่ออัปเดต todo นี้ มันจะค้นหา todo ที่จะอัปเดตตาม objectid แต่ก็ใช้ currentuser เพื่อให้แน่ใจว่า todo ที่เชื่อมโยงกับ objectid ถูกสร้างโดยผู้ใช้ที่ทำการค้นหา นี่ทำให้แน่ใจว่าคุณสามารถดู todos ที่คุณสร้างเท่านั้นและจึงปลอดภัย เรารวมขีดจำกัด 1 ผลลัพธ์เพื่อให้แน่ใจว่าเซิร์ฟเวอร์จะไม่ค้นหาต่อไปหลังจากพบ todo มีวิธีการอีกวิธีหนึ่งในการค้นหาวัตถุตาม objectid แต่ฉันไม่ชอบใช้มันเพราะมันอาจส่งคืนผลลัพธ์ที่แปลกถ้าหากไม่พบวัตถุที่เชื่อมโยงกับ objectid เรากำลังตั้งค่า ‘finisheddate’ ด้วยวันที่ปัจจุบันเมื่อวัตถุถูกอัปเดต โดยการตั้งค่า finisheddate โดยฟังก์ชันนี้เท่านั้น เราได้ทำให้แน่ใจว่า finisheddate ปลอดภัยและไม่สามารถปลอมแปลงหรือเปลี่ยนแปลงได้ เรายังใช้ ‘query equalto(“finished”, false)’ เพื่อให้แน่ใจว่าเฉพาะ todo ที่ยังไม่เสร็จเท่านั้นที่สามารถถูกทำเครื่องหมายว่าเสร็จและมีการตั้งค่า finisheddate นั่นหมายความว่าเมื่อ todo ถูกทำเครื่องหมายว่าเสร็จแล้ว มันจะไม่สามารถถูกทำเครื่องหมายว่าเสร็จอีกในภายหลังได้ parse server 3 x 1 parse cloud define("marktodoascompletedforuser", async(request) => { 2 let currentuser = request user; 3 let todoid = request params todoid; 4 let query = new parse query("todo"); 5 query equalto("user", currentuser); 6 query equalto("objectid", todoid); 7 query equalto("finished", false); 8 let todo = await query first({ usemasterkey true }); 9 if(object keys(todo) length === 0) throw new error('no results found!'); 10 todo set("finished", true); 11 let date = new date(); 12 todo set("finisheddate", date); 13 try { 14 await todo save(null, { usemasterkey true}); 15 return todo; 16 } catch (error){ 17 return("getnewstore error " + error code + " " + error message); 18 } 19 }); parse server 2 x 1 parse cloud define("marktodoascompletedforuser", function(request, response) { 2 var currentuser = request user; 3 var todoid = request params todoid; 4 var query = new parse query("todo"); 5 query equalto("user", currentuser); 6 query equalto("objectid", todoid); 7 query equalto("finished", false); 8 query limit(1); 9 query find({ 10 usemasterkey true, 11 success function (results) { 12 if (results length > 0) { 13 var todo = results\[0]; 14 todo set("finished", true); 15 var date = new date(); 16 todo set("finisheddate", date); 17 todo save(null, { 18 usemasterkey true, 19 success function (object) { 20 response success(\[todo]); 21 }, 22 error function (object, error) { 23 response error("got an error " + error code + " " + error description); 24 } 25 }); 26 } else { 27 response error("todo not found to update"); 28 } 29 30 }, 31 error function (error) { 32 response error(" error " + error code + " " + error message); 33 } 34 }); 35 }); 7\) สรุป! และนั่นคือทั้งหมด คุณได้สร้างแอป todo ที่ปลอดภัยอีกครั้ง กุญแจสำคัญในการสร้างแอปที่ปลอดภัยบนเซิร์ฟเวอร์ parse คือการปิดการอนุญาตระดับคลาสทั้งหมดสำหรับทุกคลาส ยกเว้นคลาสผู้ใช้ ในคลาสผู้ใช้ คุณจะปิดการอนุญาตทั้งหมด ยกเว้น create และ get นอกจากนี้ให้แน่ใจว่าตั้งค่า acl ของผู้ใช้ทั้งหมดเพื่อให้ผู้ใช้สามารถ get ข้อมูลของตนเองได้เท่านั้น จากนั้นการโต้ตอบทั้งหมดของคุณจะผ่านโค้ดคลาวด์และถูกกรองโดยใช้ request user หรือที่เรียกว่า currentuser ดังนั้นคุณสามารถสร้างระบบที่ปลอดภัยบน parse server และ back4app ได้แล้ว แต่รอเดี๋ยว คุณพูดว่า? แล้ว background jobs และ live queries ล่ะ? อืม คุณมีจุดที่ดี ดังนั้นฉันจะพูดถึงเรื่องนี้ในสองส่วนโบนัสถัดไป 8\) ส่วนโบนัส 1 งานเบื้องหลัง บางครั้งคุณจำเป็นต้องสร้างงานเบื้องหลังเพื่อให้ทำงานทุกชั่วโมง ทุกวัน หรือทุกสัปดาห์ หากคุณปิดการอนุญาตระดับคลาสทั้งหมด งานเบื้องหลังของคุณจะไม่สามารถสอบถามฐานข้อมูลได้ เว้นแต่จะตั้งค่าอย่างถูกต้อง นี่เป็นเรื่องที่ค่อนข้างยุ่งยาก ดังนั้นฉันจึงต้องการรวมตัวอย่างไว้ที่นี่ ในกรณีนี้เราจะสร้างงานเบื้องหลังที่ตรวจสอบฐานข้อมูลสำหรับ todo ที่ยังไม่เสร็จซึ่งมีอายุมากกว่า 1 ปี และจากนั้นทำเครื่องหมายว่าเสร็จสิ้นโดยอัตโนมัติ กลเม็ดที่นี่คือการใช้ ‘usemasterkey’ อย่างถูกต้อง มันต้องถูกเพิ่มเข้าไปในคำถามก่อนที่ then promise เพียงแค่ทำตามเทมเพลตนี้และคุณควรจะสามารถเขียนงานเบื้องหลังที่ปลอดภัยได้อย่างง่ายดาย คุณเริ่มต้นด้วยการเขียนคำถามที่คุณต้องการวนซ้ำทั่วทั้งฐานข้อมูลและจากนั้นให้แน่ใจว่ารวม status error หากมีข้อผิดพลาดและสิ้นสุดด้วย status success เพื่อให้แน่ใจว่ามันเสร็จสิ้น คุณสามารถดูบันทึกบน back4app เพื่อดูงานเบื้องหลังทำงานในขณะที่คุณเรียกใช้งาน parse server 3 x 1 parse cloud job("markunfinishedtodosolderthan1yearasfinished", async(request) => { 2 let date = new date(); 3 let intyear = date getfullyear() 1; 4 let query = new parse query("todo"); 5 query equalto("finished", intyear); 6 query lessthan("createdat", date); 7 8 let todo = await query find({ usemasterkey true }); 9 for (let i = 0; i < results length; i++) { 10 let todo = results\[i]; 11 todo set("finished", true); 12 todo set("finisheddate", date); 13 try { 14 await todo save(null, { usemasterkey true}); 15 } catch (error){ 16 console log("getnewstore error " + error code + " " + error message); 17 } 18 } 19 return "migration completed successfully "; 20 }); parse server 2 x 1 parse cloud define("marktodoascompletedforuser", function(request, response) { 2 var currentuser = request user; 3 var todoid = request params todoid; 4 var query = new parse query("todo"); 5 query equalto("user", currentuser); 6 query equalto("objectid", todoid); 7 query equalto("finished", false); 8 query limit(1); 9 query find({ 10 usemasterkey true, 11 success function (results) { 12 if (results length > 0) { 13 var todo = results\[0]; 14 todo set("finished", true); 15 var date = new date(); 16 todo set("finisheddate", date); 17 todo save(null, { 18 usemasterkey true, 19 success function (object) { 20 response success(\[todo]); 21 }, 22 error function (object, error) { 23 response error("got an error " + error code + " " + error description); 24 } 25 }); 26 } else { 27 response error("todo not found to update"); 28 } 29 30 }, 31 error function (error) { 32 response error(" error " + error code + " " + error message); 33 } 34 }); 35 }); 2 live queries บางครั้งคุณจำเป็นต้องใช้ฟีเจอร์ live query ของ parse สำหรับสิ่งต่างๆ เช่น แอปแชทสด คุณจะต้องใช้ live query เพื่อตรวจสอบเมื่อมีข้อความใหม่สำหรับผู้ใช้ของคุณถูกสร้างขึ้น live query เป็นวิธีการของ parse ในการใช้ซ็อกเก็ตเพื่อรับการอัปเดตสด มันสะดวกมาก แต่จะไม่ทำงานกับคลาสที่การอนุญาต find ถูกปิด ดังนั้นในกรณีนี้เราจะเปิดการอนุญาต find กลับมาสำหรับคลาส message และแทนที่เราจะกำหนด acl สำหรับข้อความนั้นโดยตรง acl ควรถูกตั้งค่าให้เฉพาะผู้รับเท่านั้นที่สามารถใช้ find เพื่อดึงข้อความจากเซิร์ฟเวอร์ได้ จากนั้นคุณจะเรียกใช้ pf live query ในไคลเอนต์ของคุณเพื่อค้นหาข้อความสำหรับผู้ใช้ของคุณและมันจะทำงานได้อย่างไม่มีที่ติ หากคุณกำลังจัดการกับข้อความกลุ่ม มันจะแตกต่างออกไปเล็กน้อย คุณสามารถกำหนดให้หลายคนอยู่ใน acl ได้ แต่จริงๆ แล้วมันไม่สามารถขยายได้ แทนที่จะเป็นเช่นนั้น มีวิธีที่ดีกว่า คุณตั้งค่า acl ให้ขึ้นอยู่กับบทบาท parse role และจากนั้นผู้ใช้ใดๆ ที่คุณต้องการให้เข้าถึงข้อความนั้นคุณเพียงแค่กำหนดให้พวกเขาอยู่ใน parse role นั้น หากคุณต้องการหยุดพวกเขาจากการอ่านข้อความสำหรับกลุ่มนั้น คุณเพียงแค่ลบพวกเขาออกจากบทบาทนั้น นี่ง่ายกว่าการลบพวกเขาออกจาก acl ของข้อความแต่ละข้อความและมันสามารถขยายได้สำหรับกลุ่มที่ใหญ่ที่สุด นี่คือวิธีที่ถูกต้องในการทำเช่นนี้ ฉันจะไม่ทิ้งตัวอย่างโค้ดสำหรับสิ่งนี้เพราะมันซับซ้อนเกินไปสำหรับบทเรียนนี้ แต่บางทีฉันอาจจะอธิบายวิธีการทำในบทเรียนถัดไปของฉัน ขอบคุณที่อ่านบทเรียนนี้เกี่ยวกับความปลอดภัยกับ parse และ back4app หากคุณมีคำถามโปรด ติดต่อฉัน และฉันยินดีที่จะตอบคำถามเหล่านั้น ขอบคุณ! โจเรน