30 March 2010

Grails-Security-Encryption

การเข้ารหัส (encryption) คือ การเปลี่ยนข้อความที่สามารถอ่านได้ (plain text) ไปเป็นข้อความที่ไม่สามารถอ่านได้ (cipher text) เพื่อเหตุผลด้านความปลอดภัย

ประโยชน์ของการเข้ารหัส

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

วิธีการเข้ารหัสมีความสำคัญต่อ 3 ส่วนหลักของระบบการค้าทางอิเล็กทรอนิกส์ คือ  
  • 1. ระบบตรวจสอบว่าเป็นเอกสารจริง (Authentication)
  • 2. การพิสูจน์หลักฐานว่าได้กระทำการรายการจริง (Non-Repudiation)
  • 3. การรักษาสิทธิส่วนตัว (Privacy)

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

สำหรับในเรื่องของการพิสูจน์หลักฐานว่าได้กระทำรายการจริง (Non-Repudiation) จะมีความสำคัญอย่างมากต่อการทำรายการทางธุรกิจ เนื่องจากจะใช้เป็นหลักฐานป้องกันการปฏิเสธในภายหลังว่าไม่ได้เป็นผู้ส่ง / รับ แฟ้มข้อมูล หรือไม่ได้ทำรายการทางธุรกิจนั้นๆ >>>http://th.wikipedia.org/wiki/การเข้ารหัส


ศึกษาจากตัวอย่างนะครับ ก่อนอื่นสร้าง User,UserController
  1. grails create-domain-class User แล้วใส่ code ตามนี้

    class User {
    String login
    String password
    String role = "user"
    static constraints = {
    login(blank:false, nullable:false, unique:true)
    password(blank:false, password:true)
    role(inList:["admin", "user"])
    }
    static transients = ['admin']
    boolean isAdmin(){
    return role == "admin"
    }

    def beforeInsert = {
    password = password.encodeAsSHA()
    }

    String toString(){
    login
    }
    }

  2. grails create-controller User แล้วใส่ code ตามนี้

    class UserController {

    def login = {}
    def logout = {
    flash.message = "Goodbye ${session.user.login}"
    session.user = null
    redirect(action:"login")
    }
    def authenticate = {
    def user = User.findByLoginAndPassword(
    params.login, params.password.encodeAsSHA())
    if(user){
    session.user = user
    flash.message = "Hello ${user.login}!"
    redirect(controller:"race", action:"list")
    }else{
    flash.message =
    "Sorry, ${params.login}. Please try again."
    redirect(action:"login")
    }
    }


    static allowedMethods = [save: "POST", update: "POST", delete: "POST"]

    def index = {
    redirect(action: "list", params: params)
    }

    def list = {
    params.max = Math.min(params.max ? params.int('max') : 10, 100)
    [userInstanceList: User.list(params), userInstanceTotal: User.count()]
    }

    def create = {
    def userInstance = new User()
    userInstance.properties = params
    return [userInstance: userInstance]
    }

    def save = {
    def userInstance = new User(params)
    if (userInstance.save(flush: true)) {
    flash.message = "${message(code: 'default.created.message', args: [message(code: 'user.label', default: 'User'), userInstance.id])}"
    redirect(action: "show", id: userInstance.id)
    }
    else {
    render(view: "create", model: [userInstance: userInstance])
    }
    }

    def show = {
    def userInstance = User.get(params.id)
    if (!userInstance) {
    flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])}"
    redirect(action: "list")
    }
    else {
    [userInstance: userInstance]
    }
    }

    def edit = {
    def userInstance = User.get(params.id)
    if (!userInstance) {
    flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])}"
    redirect(action: "list")
    }
    else {
    return [userInstance: userInstance]
    }
    }

    def update = {
    def userInstance = User.get(params.id)
    if (userInstance) {
    if (params.version) {
    def version = params.version.toLong()
    if (userInstance.version > version) {
    userInstance.errors.rejectValue("version", "default.optimistic.locking.failure", [message(code: 'user.label', default: 'User')] as Object[], "Another user has updated this User while you were editing")
    render(view: "edit", model: [userInstance: userInstance])
    return
    }
    }
    userInstance.properties = params
    if (!userInstance.hasErrors() && userInstance.save(flush: true)) {
    flash.message = "${message(code: 'default.updated.message', args: [message(code: 'user.label', default: 'User'), userInstance.id])}"
    redirect(action: "show", id: userInstance.id)
    }
    else {
    render(view: "edit", model: [userInstance: userInstance])
    }
    }
    else {
    flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])}"
    redirect(action: "list")
    }
    }

    def delete = {
    def userInstance = User.get(params.id)
    if (userInstance) {
    try {
    userInstance.delete(flush: true)
    flash.message = "${message(code: 'default.deleted.message', args: [message(code: 'user.label', default: 'User'), params.id])}"
    redirect(action: "list")
    }
    catch (org.springframework.dao.DataIntegrityViolationException e) {
    flash.message = "${message(code: 'default.not.deleted.message', args: [message(code: 'user.label', default: 'User'), params.id])}"
    redirect(action: "show", id: params.id)
    }
    }
    else {
    flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])}"
    redirect(action: "list")
    }
    }
    }

  3. สร้างการ encode,decode ใน grails-app/utils ไฟล์ชื่อ UnderscoreCodec.groovy

    class UnderscoreCodec {
    static encode = {target->
    target.replaceAll(" ", "_")
    }
    static decode = {target->
    target.replaceAll("_", " ")
    }
    }

  4. สร้าง encryption ใน path เดียวกัน สร้างไฟล์ชื่อ SHACodec.groovy

    import java.security.MessageDigest
    class SHACodec{
    static encode = {target->
    MessageDigest md = MessageDigest.getInstance('SHA')
    md.update(target.getBytes('UTF-8'))
    return new String(md.digest()).encodeAsBase64()
    }
    }

  5. ทดสอบกันเลย...โดยสร้าง User ใหม่ซัก 1 คน แล้วมาดูกันซิว่า password จะ encrypt หรือไม่
    จากนั้น view ดู

    เรียบร้อย ตอนนี้เราก็สามารถทำ Encryption สำเร็จ

1 comment:

  1. วันนี้เจองานหนัก แต่ไม่ถอยแน่นอนครับ ถึงแม้จะยังไม่รู้เรื่อง แต่ไม่เป็นแบบนี้ไปตลอดแน่


    --------------------------------------------------------
    วันนี้แพ้ อำนาจใฝ่ชั่วอีกแล้ว โอ้ย เกลียดมันจิงๆ ต้องพยายามเอาชนะมันให้ได้ แก้วิธีนี้ไม่ได้ เห็นทีจะต้องใช้ไม้แข็ง ซะแล้ว...

    ReplyDelete