ไม่ได้เขียนเรื่อง programming มาตั้งนานเหมือนกันเนาะ จริงๆ ก็อยากจะเขียนเยอะๆ เหมือนกันนะครับ แต่อย่างว่าอ่ะ คนมันขี้เกียจ เอ้ยยย งานเยอะ (ฮ่า ๆ ๆ ๆ)

พอดีว่าช่วงนี้ต้องหมกหมุ่นกับเรื่อง Membership Provider มากหน่อย ก็เลยได้ลองเล่นอะไรๆ ที่มันแลดูจะ advanced ขึ้นไปอีกนิด อันนี้เป็น trick ง่ายๆ ที่ใช้งานได้จริงๆ แล้วก็ค่อนข้างมีประโยชน์มากๆ เลย โดยเฉพาะในเวลาที่เราต้องการกำหนดสิทธิ์ในการเข้าถึงข้อมูลบางส่วน ... โดยมากแล้วเราจะกำหนดมันในระดับ presentation layer ซึ่งก็คือที่หน้า web page นั่นเอง แต่ว่าด้วยความสามารถของ PrincipalPermissionAttributes นั้น เราสามารถกำหนดได้ในระดับลึกลงไปถึงระดับ business/data layers หรือพูดง่ายๆ ก็คือ ทั้ง class กันเลยทีเดียว

อ่อ..เตือนก่อนนะครับ เนื้อหาที่เขียนในโพสต์นี้ ผมติ๊ต่างเอาว่าคนอ่านมีพื้นฐานเรื่อง ASP.NET Security Model มาพอสมควรนะครับ ถ้ายังไม่มี ลองไปหาอ่านก่อนก็ได้ครับ จะได้ไม่งง ไม่งั้นผมรับรองว่าจะมึนๆ งงๆ แน่นอน เอิ๊กๆๆ


ลิงค์ข้างบนทั้ง 4 อันนั้น แนะนำให้ไปลองอ่านดูนะครับ สำหรับมือใหม่เรื่อง security จะได้กระจ่างขึ้น :)

เข้าเรื่องต่อครับ ต่อไปนี้้เป็น code ตัวอย่างที่ผมไปจิ๊กเอามาจาก blog ของ Scott Guthrie นะครับ (ฟังดูหน้าด้านเนาะ ฮ่า ๆ ๆ)

การใช้งาน PrincipalPermissionAttributes นั้น ง่ายมากครับ เริ่มจากเปิดไฟล์ class ที่เราต้องการจะใส่ permission ลงไป เช่นในตัวอย่าง คือ class ชื่อ EmployeeManager

using System;

public class EmployeeManager
{
   public Employee LookupEmployee(int employeeID) { //todo }
   public void AddEmployee(Employee e) { //todo }
}

จาก code ข้างบน ใน EmployeeManager class ของเรานั้น จะมีอยู่ 2 methods นั่นคือ LookupEmployee() กับ AddEmployee() ซึ่งสมมติเราต้องการให้สิทธิ์ในการเข้าถึงข้อมูลของพนักงานจากแต่ละตำแหน่ง หรือแต่ละแผนกไม่เท่าเทียมกัน เช่น กำหนดให้เจ้าหน้าที่จาก HR เท่านั้นที่สามารถใช้งาน AddEmployee() ได้ และเจ้าหน้าที่จาก Manager เท่านั้นที่สามารถใช้ LookupEmployee() ได้

เราสามารถทำได้โดยการเรียกใช้ PrincipalPermission ครับ

using System;
using System.Security.Permissions;

[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public class EmployeeManager
{
   [PrincipalPermission(SecurityAction.Demand, Role = "Manager")]
   public Employee LookupEmployee(int employeeID) { //todo }
  
   [PrincipalPermission(SecurityAction.Demand, Role = "HR")]
   public void AddEmployee(Employee e) { //todo }
}

จาก code ข้างบนนี้ การเอา PrincipalPermission มาใช้ หมายความว่าทุกครั้งที่มี web request เข้ามาเรียกใช้ class นี้ ผู้เรียกจะต้องทำการ log in เข้ามาก่อนทุกครั้ง นั่นมาจากที่เรากำหนดไว้ว่า Authenticated = true และในระดับ method นั้น เราก็ได้กำหนดตามเงื่อนไขที่เราต้องการ นั่นคือ เฉพาะ user ที่มีอยู่ใน Manager role เท่านั้น ที่มีสิทธิ์เรียกใช้ LookupEmployee() ได้ และเฉพาะ user ที่อยู่ใน HR role เท่านั้นที่สามารถ AddEmployee() ได้ ... ง่ายมั้ยครับ :)

ถ้าเป็นสมัยก่อน เราคงต้องมานั่งเขียน code กันวุ่นวายเลยทีเดียว ไล่ตั้งแต่ การดึงข้อมูล user มาจาก database ก่อน และเขียน code อีก 4-5 บรรทัดเพื่อเทียบว่า user คนนั้นมีสิทธิ์เข้าใช้งานหรือไม่ ... ดูสิครับ เดี๋ยวนี้แค่ใส่ attribute ไปบน class/method เท่านั้นเอง... อืม นี่แหละ ผมถึงได้หันมาเขียน C# จริงๆ จังๆ แทน PHP (อิอิ)

แล้วนอกจากเราจะเขียน PrincipalPermission ให้กับ class/method แล้ว เรายังสามารถเขียนให้กับ page ได้เช่นกันครับ หลักการคล้ายๆ กัน

using System.Security.Permissions;

[PrincipalPermission(SecurityAction.Demand, Authenticated = true, Role = "Manager")]
partial class MyPage : System.Web.UI.Page
{
   // some code
}

เป็นไงครับ ง่ายดีมั้ย

ส่วนอีกคำถามที่จะโดนถามบ่อยๆ ว่า "แล้วทำไมเราต้องไปใส่ permission ในระดับ business/data layers ด้วย ในเมื่อเราสามารถใส่ที่ presentation layer ได้เลย?" คำตอบคือ การเขียนที่ business/data layers นั้น จะทำให้เรามั่นใจได้มากขึ้นครับ ว่าปลอดภัยแน่ๆ แม้ว่าในหน้าเว็บของเราอาจจะมีรูรั่วที่ไม่ได้ตั้งใจ หรือโดย hacker เจาะเข้ามาก็ตาม ยิ่งโดยเฉพาะสมัยนี้ ลูกเล่นต่างๆบนเว็บมันมีความลึกลับซับซ้อนมากขึ้นจริงๆ เราจะทำให้เราหลงๆ ลืมๆ ได้เหมือนกันว่า เอ๊..หน้านี้เราใส่ permission รึยังน๊อ??

เอาเป็นว่า จริงๆ แล้วจะใช้แบบไหนก็ขึ้นอยู่กับความสะดวกและปัจจัยอื่นๆ ส่วนตัวเลยนะครับ จะใช้อย่างไหนก็ไม่ผิดกติกาแต่อย่างใด เอาสะดวกและปลอดภัยก็เป็นอันใช้ได้ครับ

Happy coding!
mrnon

 
 
 
UPDATE: November 1, 2008
 
พอดีเมื่อตะกี๊ลองเล่น PrincipalPermission แบบหลายๆ Role ดู ปรากฏว่ามันไม่อนุญาติให้ใช้ code แบบนี้นะครับ
 
[PrincipalPermission(SecurityAction.Demand, Authenticated = true, Role = "Manager, HR")]
 
หลังจากได้ลอง Google ดูแล้ว ปรากฏว่าเราจะต้องใส่ PrincipalPermission ไปตามจำนวน Role ที่เราต้องการจะใช้ครับ เช่น สมมติว่าต้องการให้ทั้ง Manager และ HR เท่านั้นที่ใช้งานได้ ก็จะต้องใส่แบบนี้ครับ
 
[PrincipalPermission(SecurityAction.Demand, Authenticated = true, Role = "Manager")]
[PrincipalPermission(SecurityAction.Demand, Authenticated = true, Role = "HR")]

อ่า วุ่นวายดีทีเดียว แต่ก็อยู่ในระดับที่พอยอมรับได้ครับ ยังไงๆ มันก็ง่ายกว่าการมานั่งเขียน code เองอยู่แล้วล่ะเนาะ :)


Published Date: October 28, 2008 03:33:14 (GMT+7)
ชื่อ:
อีเมล:
เว็บไซต์:
ความเห็น:
CAPTCHA
ช่วยพิมพ์ตัวเลขจากรูปภาพลงในช่องข้างล่างด้วยครับ
จะได้รู้ว่าคุณเป็นคน มิใช่หุ่นยนต์มาแอบเม้นต์ผม (อิอิ)



ความคิดเห็น
ค้นหาบล็อก

บล็อกล่าสุด
ราคาน้ำมัน
อัตราแลกเปลี่ยนเงินต่างประเทศ
เริ่มเขียนตั้งแต่ 17 กันยายน 2550 © สงวนลิขสิทธิ์ ซะเมื่อไหร่ ก.ไก่ กุ๊กๆ
อยากจะก๊อปปี้อะไร ก็ก๊อปไปนะครับ อ้างอิงมาเว็บผมบ้างก็จะดี แต่ถ้าไม่ทำก็ไม่เป็นไรครับ จำไว้ๆ