Category: การทำงานกับ PSU Passport

  • บันทึกการติดตั้งเพื่อใช้งานบริการระบบยืนยันตัวตน PSU Passport (Authentik)

    ปัจจุบันบระบบยืนยันตัวตนแบบ 2 ขั้นตอน (2FA) หรือ MFA ถูกผลักดันให้ใช้งานกันอย่างแพร่หลาย ทั้งนี้เพื่อยกระดับการรักษาความปลอดภัยของระบบสารสนเทศ คณะการแพทย์แผนไทย ม.อ. มีความมุ่งหมายที่จะเปลี่ยนแปลงระบบล๊อกอินของระบบสารสนเทศต่างๆ ทั้งหมดของคณะให้เป็น 2FA ตามนโยบายความปลอดภัยของมหาวิทยาลัยฯ ด้วย

    ต่อไปนี้จะแสดงตัวอย่างการ implement ระบบเพื่อติดตั้งใช้งาน PSU Passport (Authentik) ด้วยภาษา PHP

    (more…)
  • การย่อ-ยุบแถวข้อมูลบน GridView โดยประยุกต์ใช้ร่วมกับ jQuery และ Collapse ใน Bootstrap (C#)

               จากความเดิมตอนที่แล้ว เราได้พูดถึงวิธีการจัดการข้อมูลจำนวนมากด้วยการจัดกลุ่มหมวดหมู่ของข้อมูลใน GridView กันไปแล้ว ซึ่งหากผู้อ่านท่านใดต้องการทราบวิธีการจัดหมวดหมู่สามารถตามดูเนื้อหาในบทความได้จาก การจัดหมวดหมู่แถวของข้อมูลบน GridView ด้วย C# และในส่วนของบทความนี้จะเป็นเนื้อหาต่อยอดการทำงานจากการจัดหมวดหมู่ดังกล่าว โดยเพิ่มความสามารถให้หมวดหมู่หรือกลุ่มเหล่านั้นสามารถย่อ-ยุบได้ เพื่ออำนวยความสะดวกให้กับผู้ใช้ในการดูข้อมูลแยกส่วนกันชัดเจนมากยิ่งขึ้น หรือเพื่อตอบโจทย์ให้กับผู้ใช้บางท่านที่อาจมีความต้องการดูข้อมูลทีละส่วนได้ โดยจะนำ Component ที่ชื่อว่า Collapse ใน Bootstrap มาประยุกต์ใช้ในการแสดงผลร่วมกับ GridView และยังมี jQuery มาเป็นอีกหนึ่งตัวช่วยเพื่อให้สามารถแสดงผลตามที่ต้องการได้ โดยการอธิบายในบทความนี้ ทางผู้เขียนจะขอตัดตอนในส่วนของรายละเอียดขั้นตอนวิธีการจัดหมวดหมู่ไป และข้ามมาพูดถึงขั้นตอนที่ต้องจัดทำเพิ่มเติมในการทำย่อ-ยุบเลยละกันนะคะ

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

    • data-toggle=”collapse
    • data-target=”.multi-collapse” เพื่อกำหนด target ที่เราต้องการให้ย่อยุบได้ โดยใช้สไตล์ชีทเป็นตัวช่วยเพื่อแยกแต่ละกลุ่มออกจากกัน ซึ่งในที่นี้จะตั้งชื่อสไตล์ชีท multi-collapse ตามด้วยรหัสของประเภทกลุ่มนั้น โดยต้องระบุสไตล์ชีทนี้ให้กับแถวย่อย(child)ด้วย
    • aria-controls=”demo1 demo2 demo3 demo4 demo5” เพื่อกำหนดพื้นที่ที่จะย่อยุบ โดยสามารถกำหนดได้มากกว่า 1 พื้นที่ ซึ่งจะแยกด้วยการเว้นวรรคชื่อ id ของแถวย่อย(child) ในตัวอย่างนี้ คือ แถวย่อยของแถวหลักนี้ ประกอบด้วย 5 แถว คือ แถวที่มี id ชื่อ demo1,demo2,demo3,demo4, demo5 นั่นเอง
    • class = “collapseToggle” เป็นการระบุสไตล์ชีทเพื่อใช้ในการระบุตำแหน่งในการเปลี่ยนไอคอนเวลากดย่อ-ยุบ โดยเรียกใช้งานผ่าน jQuery(ซึ่งจะกล่าวถึงในส่วนถัดไป)

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

    1. ปรับแก้ในส่วนของ GroupGv_DataBound เพิ่มเติม เพื่อกำหนดค่าที่ระบุไว้ข้างต้นในแถวของหมวดหมู่ที่แทรกเข้ามา

    string lastCatName = "";
    string AllName = "";
    
     
    protected void GroupGv_DataBound(object sender, EventArgs e)
            {
                lastCatName = "";
                Table table = (Table)GroupGv.Controls[0];
    
                foreach (GridViewRow row in GroupGv.Rows)
                {
                  
                    HiddenField HidCatName = (HiddenField)row.FindControl("HidCatName");
                    HiddenField HidCatID = (HiddenField)row.FindControl("hdCatID");
                    HiddenField HidID = (HiddenField)row.FindControl("hdID");
    
                    ////ตั้งชื่อ id ให้กับแถวย่อย(child) แต่ละแถว
                    row.Attributes.Add("id", "Name" + HidID.Value);
    
                   ////กำนดสไตล์ชีทของตัวแถวย่อยและระบุเพื่อให้ย่อยุบได้ ด้วย accordian-body collapse และระบุพื้นที่เพื่อให้อ้างถึงจากแถวหลัก(parent)ได้ 
                  /////ซึ่งเป็นในส่วนของ multi-collapse จะเป็น multi-collapse ตามด้วยชื่อรหัสประเภทนั่นเอง 
                  /////โดยแถวย่อย(child) ที่มีแถวหลัก(parent)เดียวกัน ค่าของ multi-collapse จะตรงกันและตรงกับค่า target ที่ระบุไว้ในแถวหลัก(parent)ด้วย
    
                    if (row.RowState == DataControlRowState.Alternate)  ////กรณีที่ต้องการให้แต่ละแถวสลับสีกันเพื่อให้ง่ายต่อการดูข้อมูล 
                       row.CssClass = "Blue accordian-body collapse multi-collapse" + HidCatID.Value;
                    else               
                      row.CssClass = "accordian-body collapse multi-collapse" + HidCatID.Value;
    
                    if (HidCatName.Value != lastCatName)
                    {
    
                       ////////วนเพื่อหาจำนวน child ในแต่ละประเภทเพื่อใช้ในการกำหนด aria-controls
    
                        var strList = GroupData.Select("CategoryID='" + HidCatID.Value + "'");
                        foreach (DataRow dr in strList)
                        {
                            AllName += " Name" + dr["ID"];
                        }
    
                       //// เป็นการหาผลรวมค่าของฟิลด์ Amt ซึ่งหมายถึงจำนวน โดยเป็นการรวมค่าฟิลด์แยกตามแต่ละ CategoryID นั่นเอง
    
                        var sumOfValuesInCategory = GroupData.AsEnumerable().Where(x => x.Field<string>("CategoryID") == HidCatID.Value).Sum(x => x.Field<int>("Amt")).ToString();
                       
                        int realIndex = table.Rows.GetRowIndex(row);
                        string text = HidCatName.Value;
                        GridViewRow newHeaderRow = new GridViewRow(realIndex, 0, DataControlRowType.Header, DataControlRowState.Normal);
    
                        /////กำหนดค่าต่างๆ (data-toggle  data-target  aria-controls )ให้กับแถว เพื่อให้สามารถย่อ-ยุบได้ 
    
                        newHeaderRow.Attributes.Add("data-toggle", "collapse");
                        newHeaderRow.Attributes.Add("data-target", ".multi-collapse" + HidCatID.Value);
                        newHeaderRow.Attributes.Add("aria-expanded", "true");
                        newHeaderRow.Attributes.Add("aria-controls", AllName);
    
                        TableCell newCell = new TableCell();
                        newHeaderRow.Cells.AddAt(0, newCell);
    
                       /////ปรับแก้การระบุค่า ColumnSpan จากเดิมที่รวมกันทุกคอลัมน์(GroupGv.Columns.Count) 
                       //// แต่กรณีนี้ต้องเว้นคอลัมน์ไว้แสดงผลจำนวนรวมแต่ละประเภทด้วย
    
                        newCell.ColumnSpan =1;
                        newCell.BackColor = System.Drawing.Color.FromName("#399ea9"); ;
                        newCell.ForeColor = System.Drawing.Color.White;
                        newCell.Font.Bold = true;
                        newCell.Attributes.Add("class", "collapseToggle");
    
                        /////ใส่ไอคอน + หน้าข้อความชื่อประเภท เพื่อบอกให้ทราบว่าสามารถกดย่อ-ยุบได้
                        newCell.Text = "<i class='fas fa-plus mr-2'></i>" + string.Format(HidCatName.Value, "&nbsp;{0}", text);
    
                        ///สร้าง TableCell หรือคอลัมน์ใหม่ เพื่อแสดงผลข้อมูลจำนวนรวมของแต่ละประเภท 
    
                        TableCell newCellTotal = new TableCell();
    
                        /////เพิ่ม TableCell ในแถวที่กำลังสร้างและระบุค่าต่างๆ
                        newHeaderRow.Cells.AddAt(1, newCellTotal);
                        newCellTotal.ColumnSpan = 1;
                        newCellTotal.BackColor = System.Drawing.Color.FromName("#399ea9"); ;
                        newCellTotal.ForeColor = System.Drawing.Color.White;
                        newCellTotal.Font.Bold = true;
                        newCellTotal.HorizontalAlign = HorizontalAlign.Right;
    
                        ////นำค่าผลรวมในตัวแปร sumOfValuesInCategory ที่คำนวณได้ข้างต้นมาจัดรูปแบบก่อนแสดงผลใน TableCell สร้าง
    
                        newCellTotal.Text = string.Format("{0:#,##0}",int.Parse(sumOfValuesInCategory));
                        newCellTotal.Attributes.Add("class", "collapseToggle");
                        table.Controls.AddAt(realIndex, newHeaderRow);
                    
                          AllName = "";
    
                    }
                    lastCatName = HidCatName.Value;
                }
            }

    2.จัดทำให้ไอคอนสามารถเปลี่ยนเป็น + หรือ – ได้ เมื่อกดย่อ-ยุบ ด้วย jQuery

     <script>
         $(document).ready(function () {
    
    ///เมื่อมีการคลิก element ที่มีสไตล์ชีท collapseToggle จะทำการเปลี่ยนค่าไอคอน หากเป็นภาพบวกจะเปลี่ยนเป็นลบ หากเป็นเครื่องหมายลบจะเปลี่ยนเป็นเครื่องหมายบวก
                $('.collapseToggle').click(function () {
                    $(this).find('i').toggleClass('fa-plus fa-minus');
                });
            });
    </script>

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

        <style>
            .collapseToggle {
                cursor: pointer;
            }
        </style>

    ผลลัพธ์

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

    1. เพิ่มคำว่า “show” เข้าไปในสไตล์ชีทตอนกำหนดให้แถวย่อย ดังนี้ค่ะ

    แบบเดิม

                    if (row.RowState == DataControlRowState.Alternate)  ////กรณีที่ต้องการให้แต่ละแถวสลับสีกันเพื่อให้ง่ายต่อการดูข้อมูล 
                       row.CssClass = "Blue accordian-body collapse multi-collapse" + HidCatID.Value;
                    else               
                      row.CssClass = "accordian-body collapse multi-collapse" + HidCatID.Value;

    แบบใหม่

                      if (row.RowState == DataControlRowState.Alternate)  ////กรณีที่ต้องการให้แต่ละแถวสลับสีกันเพื่อให้ง่ายต่อการดูข้อมูล 
    
                        row.CssClass = "Blue accordian-body collapse show multi-collapse" + HidCatID.Value;
                    else
                        row.CssClass = "accordian-body collapse show multi-collapse" + HidCatID.Value;

    2.ปรับแก้ให้ไอคอนแรกที่ต้องการแสดงเป็นเครื่องหมายลบ ดังนี้ค่ะ

    แบบเดิม

                       /////ใส่ไอคอน + หน้าข้อความชื่อประเภท เพื่อบอกให้ทราบว่าสามารถกดย่อ-ยุบได้
                        newCell.Text = "<i class='fas fa-plus mr-2'></i>" + string.Format(HidCatName.Value, "&nbsp;{0}", text);

    แบบใหม่

                        /////ใส่ไอคอน + หน้าข้อความชื่อประเภท เพื่อบอกให้ทราบว่าสามารถกดย่อ-ยุบได้
                        newCell.Text = "<i class='fas fa-minus mr-2'></i>" + string.Format(HidCatName.Value, "&nbsp;{0}", text);

    ผลลัพธ์

              จากตัวอย่าง การแสดงผลครั้งแรกก็จะเปลี่ยนเป็นขยายทั้งหมด และแสดงไอคอนเป็นเครื่องหมายลบ(-)ตั้งต้นไว้ให้ และสามารถย่อ-ยุบตามปกติได้แล้วค่ะ

    เพิ่มเติม

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

    1. สร้างปุ่ม 2 ปุ่ม เพื่อกดขยายทั้งหมด และย่อทั้งหมด

    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <div class="col pull-right">
                    <asp:LinkButton ID="lnkShowAll" runat="server" CssClass="btn btn-sm btn-info mb-1" OnClientClick="javascript:ShowHideAll('1');return false;"><i class="fas fa-eye"></i>แสดงทั้งหมด</asp:LinkButton>
                    <asp:LinkButton ID="lnkHideAll" CssClass="btn btn-sm btn-info mb-1" OnClientClick="ShowHideAll('0');return false;" runat="server"><i class="fas fa-eye-slash"></i>ซ่อนทั้งหมด</asp:LinkButton>
                </div>
    
    
            </ContentTemplate>
        </asp:UpdatePanel>

    2. เขียนฟังก์ชั่นในการซ่อน/แสดงทั้งหมด

    <script>
        
     function ShowHideAll(flag) {
    
              /////ล้างค่าการระบุการแสดงผลและการแสดงไอคอนทั้งหมด ทำให้ทุกแถวยุบอยู่ จนกว่าจะมีการสั่งให้ show
                $(".accordian-body").removeClass("show");
                $(".collapseToggle").find('i').removeClass("fa-plus").removeClass("fa-minus");
    
             /////กรณีต้องการให้แสดงจะเพิ่มสไตล์ชีท show ให้กับทุกแถว และแสดงไอคอนเป็น - ทั้งหมด เพื่อให้กดย่อได้
    
                if (flag == '1') {
                    $(".accordian-body").addClass("show");
                    $(".collapseToggle").find('i').addClass("fa-minus");
                }
            /////กรณีต้องการให้แสดงจะแสดงไอคอนเป็น + ทั้งหมด เพื่อให้กดขยายได้
                else
                    $(".collapseToggle").find('i').addClass("fa-plus");
                }
    
    </script>

    ผลลัพธ์

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

              ทั้งหมดนี้ก็เป็นเพียงหนึ่งในตัวอย่างวิธีการที่จะแก้ปัญหาในการแสดงผลข้อมูลแบบตารางด้วย GridView แบบจัดกลุ่มและสามารถย่อ-ยุบข้อมูลภายในกลุ่มได้ โดยนำความสามารถของ Component อย่าง collapse ใน Bootstrap เข้ามาช่วยเท่านั้น แต่ในส่วนของรูปแบบ วิธีการ แต่ละท่านสามารถปรับเปลี่ยนและพลิกแพลงเพิ่มเติมได้ตามความเหมาะสม อีกทั้งยังสามารถนำเกร็ดความรู้นี้ไปประยุกต์ใช้กับงานของท่านได้อีกด้วย และขอบคุณที่ติดตามนะคะ ^^

    แหล่งอ้างอิง

    https://getbootstrap.com/docs/4.0/components/collapse/
    https://www.geeksforgeeks.org/how-to-change-symbol-with-a-button-in-bootstrap-accordion/

  • การเชื่อมต่อ OAuth2 ด้วย WordPress

    อยาก  Login ด้วย OAuth2 กับ WordPress ต้องทำอย่างไร

    สำหรับตัวอย่างนี้จะทำการติดตั้งบน WordPress 5.1 ผ่าน Plugin Simple Single Sign On

    • หลังจากติดตั้ง WordPress เสร็จ เข้าหน้า Administrator แล้วทำการกด Install เพื่อเข้าไปยังหน้าติดตั้ง Extension เพิ่มเติม ทำการเพิ่มปลั๊กอินใหม่ดังรูป

    • ทำการค้นหา single sign on และทำการ Install Now

    • จากนั้นทำการกด Activate

    • จากนั้นทำการตั้งค่าโดยข้าม Step 1 ไปตั้งค่า Step 2 เนื่องจากได้มีการตั้งค่า WP OAuth Server ให้รองรับไว้อยู่แล้ว

    • หลังจากนั้นทำการทดสอบ Login โดยกดปุ่ม Single Sign On

    เพิ่งเท่านี้ก็จะสามารถใช้งานได้ แต่ยังเป็นแบบเลือกได้ว่าจะ Login แบบ Local หรือผ่าน OAuth โดยอาจจะทำเป็นปุ่มในหน้าแรกเพื่อให้กด Login ก็ได้เช่นกัน

  • การเชื่อมต่อ OAuth2 ด้วย Joomla

    อยาก  Login ด้วย OAuth2 กับ Joomla ต้องทำอย่างไร

                 สำหรับตัวอย่างนี้จะทำการติดตั้งบน Joomla 3.9.3 ผ่าน Plugin MiniOrange OAuth Client

    • หลังจากติดตั้ง Joomla เสร็จ เข้าหน้า Administrator แล้วทำการกด Install เพื่อเข้าไปยังหน้าติดตั้ง Extension เพิ่มเติม

    • หลังจากนั้นกด Add Install from Web

    • ค้นหาชื่อ oauth

    • ติดตั้ง miniOrange OAuth Client 

    • หลังจากติดตั้งเสร็จให้ทำการเปิด Plugins เพิ่มเติมดังรูป

    • จากนั้นทำการตั้งค่าโดยสำหรับ miniOrange ต้องสมัครใช้งานก่อน เพราะมีทั้งแบบฟรีและไม่ฟรี แต่เราจะใช้เฉพาะในส่วนของฟรี

    • ในการสมัครต้องใส่ email และตั้งรหัสผ่าน

    • หลังจากติดตั้ง Joomla เสร็จให้ทำการกด Install เพื่อเข้าไปยังหน้าติดตั้ง Extension เพิ่มเติม

    • จากนั้นทำการตั้งค่าเกี่ยวกับ OAuth

    • สามารถกดทดสอบการ Authen ได้ที่ปุ่ม Test Configuration

    • จะปรากฎหน้า Login เพื่อเข้าสู่ระบบ

     

    •  

    • หลังจาก Login เสร็จจะคืนค่า User Profile ดังรูป

              ในการเอาไปใช้งานต่อให้ทำการสร้างปุ่ม ชี้ไปยัง http://localhost/joomla/?morequest=oauthredirect&app_name=other เพื่อเข้าใช้งาน OAuth ลองไปทำต่อดูครับ

  • เรียนรู้เทคโนโลยี OAuth2

    OAuth2 คืออะไร ทำไมต้องใช้

                 OAuth2 คือมาตรฐานหนึ่งของระบบยืนยันตัวตน และจัดการสิทธิ์การเข้าใช้งานระบบต่าง ๆ เป็นมาตรฐาน rfc6747[1] ที่ใช้สำหรับ Client เชื่อมต่อกับ Server ที่ใช้ในการ Authen & Authorize เพื่อให้ได้รับสิ่งที่เรียกว่า Access Token เพื่อใช้แทน Username และ Password (สามารถใช้อย่างอื่นเพื่อขอ Token ก็ได้) เพื่อนำไปใช้กับบริการอื่น ๆ ทำให้มีความปลอดภัยมากขึ้น รวมถึงบอกว่าทำมีสิทธิ์ทำอะไรได้บ้างกับบริการนั้น ๆ (จริง ๆ แล้วถ้า Access Token หลุดก็เอาไปเข้าระบบอื่น ๆ ได้ อาจจะต่างตรงแค่ไม่เห็น Password) โดยแนะนำต้องใช้คู่กับ https อีกชั้นเพื่อความปลอดภัยสูงสุด โดยแสดงภาพคร่าว ๆ เป็น Protocol Flow ดังรูป[2]

                  โดย Access Token จะมีเวลาจำกัดในการใช้งานเมื่อ Token หมดอายุ ก็ต้องไปขอใหม่ เมื่อเลิกใช้งานก็ขอยกเลิก Token รูปแบบการใช้งานมี 4 รูปแบบหรือเรียกว่า grant_type โดยแต่ละแบบมีรายละเอียดดังนี้[3]

    1. Authorization Codeใช้สำหรับ Web Server ที่ใช้ Code ด้านหลังในการเชื่อมต่อกับ OAuth Server โดยไม่ได้เปิดเผยให้สาธารณะเห็น อธิบายเป็นลักษณะการใช้งานคือ
      – ผู้ใช้งานเข้า Web Site
      – จะมีให้กด Login Facebook, Twitter, Google หรืออื่น ๆ 
      – เมื่อผู้ใช้กดก็จะเด้งให้ไป Login ที่ผู้ให้บริการนั้น ๆ ถ้าเคย Login ไว้แล้วก็จะข้ามขั้นตอนนี้ไป
      – ถ้าผู้ให้บริการนั้น ๆ เช่น Facebook จะให้กดยอมรับข้ออนุญาต ส่วนมากจะถามเรื่องสิทธิ์ในการเข้าถึงข้อมูลส่วนตัว
      – เมื่อผู้ใช้กดอนุญาต ก็จะกลับมายัง Web Site โดยในเบื้องหลัง WebSite จะได้ authorization code มาเรียกร้อยแล้วจากผู้ให้บริการ
      – จากนั้นทาง Web Site ก็สามารถเข้าถึงข้อมูลของผู้ให้บริการนั้น ๆ ได้ตามสิทธิที่อนุญาตไว้


      วิธีใช้ authorization code

      1. มีปุ่ม login ซึ่งมี link มี parameter คล้ายๆแบบนี้
        https://[oauth-server]/authorize?response_type=code&client_id=testclient&client_secret=testpass&redirect_uri=http%3A%2F%2F10.1.0.20%3A32778%2F%3Fauth%3Dsso
      2. เมื่อกดปุ่ม login ระบบจะต้องแจ้งว่า จะขอใช้สิทธิเรื่องใดบ้าง

      3. เมื่อผู้ใช้กดตกลงอนุญาต หน้าจอจะถูกพาไปยัง redirect_uri ที่ระบุไว้ พร้อมทั้งส่ง authorization code มาให้ด้วย
      4. ซึ่งจะมีหน้าตาประมาณนี้
         https://yoursite.com/oauth/callback?code=xxx 
      5. อ่าน code ออกมาเพื่อนำไปขอ access_token กับ API ของผู้ให้บริการ login ตัวนั้นๆ
         POST https://api.blah.com/oauth/token?grant_type=authorization_code&code=xxx&redirect_uri=xxx&client_id=xxx&client_secret=xxx 
        

        ค่า client_id, client_secret โดยมาก เจ้าของ login API (Identity provider) จะเป็นคนกำหนดมาให้

        หลังจากส่ง code ด้วย HTTP method POST และบอกว่าเป็น grant_type แบบ authorization_code ไปแล้ว client จะได้ access_token กลับมา เราจะเอา access_token นั้นในการเรียก API อื่น ๆ ต่อไป

    2. Implicit

      ใช้สำหรับ App ฝั่ง Client ซึ่งไม่จำเป็นต้องมี Web Server เป็นเหมือนการคุยระหว่าง Web Browser Client กับ OAuth Server ตรง ๆ เหมาะกับพวกที่ลงท้ายด้วย JS เช่น ReactJS, AngularJS ที่ต้องการดึงข้อมูลด้วย Browser เลย (เหมาะกับ Mobile เป็นพิเศษ) ลักษณะการทำงานคล้าย ๆ กับข้อ 1 แต่จะต่างกันตรงไม่ต้องส่ง Client_Secret เป็นวิธีที่เปิดเผยให้สาธารณะเห็น

      วิธีใช้ Implicit

      1. สร้างปุ่ม login ที่ส่ง action ไปยัง URL แบบนี้
         https://login.blah.com/oauth?response_type=token&client_id=xxx&redirect_uri=xxx&scope=email 
      2. เมื่อผู้ใช้กดปุ่ม จะแสดงหน้าต่างขอใช้สิทธิ หากตกลงข้อมูลจะ submit ไป server แล้วข้อมูล token จะถูกส่งกลับมาตาม redirect_uri ที่กำหนดเอา
      3. client_id ในข้อ 1 id provider เป็นคนกำหนดมาให้
      4. token ที่ได้มา เอาไปใช้ได้ดึงข้อมูลตามสิทธิ์ที่ได้มาได้เลย
    3. Password Credentials

      ใช้สำหรับ Application ที่มีการจัดการสิทธิเอง แต่ต้องการยืนยันตัวตนเท่านั้น ซึ่งวิธีนี้ไม่ต้อง Redirect ไปที่ผู้ให้บริการอื่น วิธีนี้เหมาะกับการใช้งานที่เป็นบริการของตัวเอง เพราะ username password จะปรากฎในเครื่องที่ส่งขอ token ถ้าไปรันวิธีนี้บน Server อื่นที่ไม่ได้เป็นเจ้าของ แสดงว่า เขาอาจจะดักเอา username password ไปใช้ก็ได้


      การใช้ Password Credentials

      1. มี form รับ username/password เมื่อกด submit แล้ว ส่ง form submit (POST method) ไปยัง server/service ของเรา
         POST https://login.blah.com/oauth/token?grant_type=password&username=xxx&password=xxx&client_id=xxx 
      2. จะได้ access_token มาใช้งานได้เลยหากใส่ข้อมูลถูกต้อง
    4. Client Credentials

      ในกรณีที่เป็นการคุยระหว่าง Application -> Service โดยจะไม่เกี่ยวข้องกับผู้ใช้ ยกตัวอย่างว่าเราอาจจะได้ข้อมูลสักอย่างแต่ต้องการความปลอดภัยว่าต้องเป็นเครื่องที่เราให้สิทธิ์ ก็สามารถส่ง id และ secret ที่ออกให้ Application ส่งมาขอ token เพื่อเข้าถึง Service นั้น ๆ ได้เลย

    OAuth2 ปลอดภัยหรือไม่

          อยู่ที่การใช้งาน ว่าปลอดภัยหรือไม่ ถ้ารันบน http ธรรมดา ยังไงก็ไม่ปลอดภัย ถ้าใช้ php 4/5 หรือ windows 2003/2008/2008/2008 R2 ยังไงก็ไม่ปลอดภัย 

    แล้วทำไมต้องใช้ OAuth2

    – เนื่องจากเป็นมาตรฐานที่พัฒนาจาก OAuth1.0a ที่มีการใช้งานมาก ทำให้ Version 2 ซึ่งลดความซับซ้อนลง การใช้งานจึงเข้าใจง่ายขึ้น

    – เร็วกว่า xml web service ใช้ json ในการสื่อสาร เพราะขนาดข้อมูลที่ส่งจะเล็กกว่ามาก

    – มีผู้ให้บริการภายนอกหลากหลาย

    – เหมาะกับใช้งานที่หลากหลาย เพราะรองรับหลากหลายภาษา (Java, Python, Go, .NET. Ruby, PHP, .NET, ฯลฯ)

    – สามารถประยุกต์นำมาใช้งานเป็น Single Sign On ได้ (ต้องพัฒนาเพิ่มเอง ไม่มีมาให้ในมาตรฐาน)

    =================================================

    References :
    [1] The OAuth 2.0 Authorization Framework : https://tools.ietf.org/html/rfc6749

    [2] An Introduction to OAuth2 : https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2

    [3] OAuth 2.0 clients in Java programming, Part 1, The resource owner password credentials grant : https://www.ibm.com/developerworks/library/se-oauthjavapt1/index.html

  • การเชื่อมต่อ OAuth2 ด้วย .NET C#

    อยาก  Login ด้วย OAuth2 กับ .NET C# ต้องทำอย่างไร

                 สำหรับตัวอย่างนี้เอามาจาก GitHub Project : https://github.com/titarenko/OAuth2[1]
    ซึ่งเป็น Code ตัวอย่างนำมาเพิ่ม ในส่วนของการเชื่อมต่อ PSU Passport ดังนี้

    • เพิ่ม class file ใน project OAuth2->Client->Impl ชื่อ PassportClient.cs เนื้อหาดังนี้
      using Newtonsoft.Json.Linq;
      using OAuth2.Configuration;
      using OAuth2.Infrastructure;
      using OAuth2.Models;
      
      namespace OAuth2.Client.Impl
      {
       /// <summary>
       /// Passport authentication client.
       /// </summary>
       public class PassportClient : OAuth2Client
       {
          /// <summary>
          /// Initializes a new instance of the <see cref="PassportClient"/> class.
          /// </summary>
          /// <param name="factory">The factory.</param>
          /// <param name="configuration">The configuration.</param>
          public PassportClient(IRequestFactory factory, IClientConfiguration configuration)
              : base(factory, configuration)
          {
          }
      
          /// <summary>
          /// Defines URI of service which issues access code.
          /// </summary>
          protected override Endpoint AccessCodeServiceEndpoint
          {
              get
              {
                  return new Endpoint
                  {
                       BaseUri = "https://oauth.psu.ac.th",
                       Resource = "?oauth=authorize"
                  };
              }
          }
      
          /// <summary>
          /// Defines URI of service which issues access token.
          /// </summary>
          protected override Endpoint AccessTokenServiceEndpoint
          {
              get
              {
                  return new Endpoint
                  {
                       BaseUri = "https://oauth.psu.ac.th",
                       Resource = "?oauth=token"
                  };
              }
          }
      
          /// <summary>
          /// Defines URI of service which allows to obtain information about user which is currently logged in.
          /// </summary>
          protected override Endpoint UserInfoServiceEndpoint
          {
              get
              {
                  return new Endpoint
                  {
                       BaseUri = "https://oauth.psu.ac.th",
                       Resource = "?oauth=me"
                  };
              }
          }
      
          /// <summary>
          /// Friendly name of provider (OAuth2 service).
          /// </summary>
          public override string Name
          {
              get { return "Passport"; }
          }
      
      
          /// <summary>
          /// Should return parsed <see cref="UserInfo"/> from content received from third-party service.
          /// </summary>
          /// <param name="content">The content which is received from third-party service.</param>
          protected override UserInfo ParseUserInfo(string content)
          {
              var response = JObject.Parse(content);
              return new UserInfo
              {
                   Id = response["user_login"].Value<string>(),
                   FirstName = response["user_login"].Value<string>(),
                   LastName = "",
                   Email = response["user_email"].SafeGet(x => x.Value<string>())
              };
          }
        }
      }
      
    • จากนั้นทำการแก้ไข Web.config ใน Project OAuth2.Example เพิ่มข้อความดังนี้
       <add clientType="PassportClient"
       enabled="true"
       clientId="testclient3"
       clientSecret="testpass3"
       redirectUri="~/auth" />
    • โดยต้องแจ้ง Redirect URI ให้ผู้ดูแลระบบ จากนั้นทางผู้ดูแลระบบจะแจ้ง Client ID และ Client Secret รวมถึงชื่อ Server ในการใช้งานให้ทราบ (ชื่อ server ใส่ในไฟล์ก่อนหน้านี้)
    • เมื่อรันโปรแกรม จะปรากฎหัวข้อ Login มากมายให้เลือก ให้ทดสอบในส่วนของ Login passport
    • หลังจากนั้นจะปรากฎหน้า Login ซึ่งอันนี้หน้าตาแล้วแต่ผู้ดูแลจะสร้างครับ (อันนี้ผมทำแค่เป็นตัวอย่างนะครับ)
    •  หลักจากนั้นจะปรากฎหน้าถามเพื่อขออนุญาตให้สิทธิ์การใช้งาน
    • จากนั้นระบบจะเด้งกลับมายังหน้าแรกแต่จะแสดงข้อความ Profile ดังรูป
    •   ตัวอย่างนี้ในการใช้งานจริงต้องนำไปประยุกต์เองครับ ซึ่งแสดงให้เห็นวิธีการใช้งาน OAuth สำหรับ .NET C# ว่าวิธีไม่ได้ต่างกับการใช้งาน CMS แต่อย่างใดครับ

    ==================================

    Reference :

    [1] OAuth2 client implementation for .NET : https://github.com/titarenko/OAuth2

  • Workshop : PSU Passport OAuth2

    มีวิธี Authen แบบอื่นนอกจาก LDAP กับ Web Service ไหม

                ด้วยยุคสมัยเปลี่ยนไป ด้วยเทคโนโลยี OAuth2 ทำให้เราจำเป็นต้องศึกษาหาความรู้เพิ่มเติมกันอีกครั้งครับ

    หมายเหตุ : เนื่องจากต้องการให้เป็น Blog เปิดเผยได้ จึงขอไม่ระบุชื่อ Server จริง ๆ ลงไปนะครับ 


    โดยรวบรวม Blog แบ่งเป็น 7 Blog ดังนี้

    Blog ที่ ชื่อ Blog
         1 เรียนรู้เทคโนโลยี OAuth2
         2 การติดตั้ง Postman
         3 ทดสอบเชื่อมต่อ OAuth2 ด้วย Postman
         4 การเชื่อมต่อ OAuth2 ด้วย Joomla
         5 การเชื่อมต่อ OAuth2 ด้วย Wordpress
         6 การเชื่อมต่อ OAuth2 ด้วย .NET C#
         7 การเชื่อมต่อ OAuth2 ด้วย PHP (กำลังดำเนินการ)

    บทความและ Link เพิ่มเติม

    [1] การยืนยันตัวตนและกำหนดสิทธิ์ Apache UserGrid 2.x

    [2] รวม Code สำหรับเชื่อมต่อ OAuth ทุกภาษา 1 : https://oauth.net/code/

    [3] รวม Code สำหรับเชื่อมต่อ OAuth ทุกภาษา 2 : https://developer.byu.edu/docs/consume-api/use-api/follow-sample-code

  • มาติดตั้ง ADLdap เพื่อใช้ยืนยันตัวตนให้กับ Owncloud 8.0 กันดีกว่า

    การติดตั้ง ADLdap เพื่อใช้ยืนยันตัวตนกับ Owncloud 8.0 นี้จะไม่อธิบายการติดตั้ง owncloud ครับ ซึ่งสามารถเข้าไปดูการติดตั้งได้ที่นี้
    How to: install Owncloud (Easy method) – เกรียงไกร หนูทองคำ
    หรือ
    ติดตั้ง ownCloud เลือกใช้ user PSU Passport หรือ ftp server หรือ RADIUS Server – วิบูลย์ วราสิทธิชัย
    การแบ่งปันความรู้ครั้งนี้จะแนะนำวิธีการนำเอา ADLdap (PHP Library) มาใช้งานร่วมกับ Owncloud เท่านั้นครับ ว่ามีวิธีการและขั้นตอนอย่างไร ซึ่งไม่ยากเกินไปครับ ^^


    ภาพรวมเมื่อทำการติดตั้ง/ตั้งค่า ADLdap สำเร็จ

    1. ลดขั้นตอนการยืนยันตัวตน ซึ่งขั้นตอนนั้นจากเริ่มจาก เซิร์ฟเวอร์ที่ติดตั้ง Owncloud ไปยัง เซิร์ฟเวอร์ Ldap โดยตรง ทำให้ไม่จำเป็นต้องติดตั้งระบบ Authen ในเซิร์ฟเวอร์ Owncloud นี้
    2. สามารถจำกัดบุคลากรที่จะเข้ามาใช้งานได้ ตามคณะ/หน่วยนั้นๆ


    ซอร์ฟแวร์ที่นำมาใช้งาน

    – ubuntu server 14.04.02 (x64)
    – Owncloud 8.0.2
    – PHP 5.5
    – ADLdap 4.0.4 – ดาวน์โหลดได้ที่นี้

    คำแนะนำ หากมีการอัพเดทจาก เวอร์ชั่น 8.0.2 ไปเป็น 8.0.3 หรือเวอร์ชั่นที่สูงกว่า เรียบร้อยแล้ว
    จะต้องทำตามขั้นตอนที่ 4 อีกครั้งครับ 

    ขั้นตอนการติดตั้ง
    1. เข้าสู่ระบบด้วย username ของ admin จากนั้นให้ไปเปิดใช้งาน App โดยคลิ๊กที่เมนู Apps จากนั้นเลือก +Apps ให้คลิ๊กเมนู not enable ดูที่ชื่อ App External user support ให้คลิ๊ก Enable

    12
    ** ขั้นตอนที่ 2-5 จะต้องทำการ ssh ไปยังเซิร์ฟเวอร์ที่ติดตั้ง owncloud ครับ
    ** path ที่ใช้ติดตั้ง owncloud ของบทความนี้ /var/www/owncloud/ ครับ

    2. ให้แตกไฟล์  adLDAP_4.0.4r2.zip จากนั้นให้ Rename ชื่อแฟ้มเป็น adldap (จะ Rename หรือไม่ก็ได้ แต่ต้องอ้างเส้นทางและชื่อแฟ้มให้ถูกต้อง) แล้วไปวางไว้ตำแหน่งนี้ /var/www/owncloud/3rdparty/

    3. เพิ่ม code โดยเข้าไปที่ไฟล์ /var/www/owncloud/config/config.php

    /// AD LDAP ///
    ‘user_backends’ => array(
    0 => array(
    ‘class’ => ‘OC_User_ADLDAP’,
    ‘arguments’ => array(
    0 => ‘dc7.psu.ac.th’,
    ),
    ),
    ),
    /// END /// 

    เมื่อเพิ่มแล้วจะได้ตามนี้

    <?php
    $CONFIG = array (
    ‘instanceid’ => ”,
    ‘passwordsalt’ => ”,
    ‘secret’ => ”,
    ‘trusted_domains’ =>
    array (
    0 => ‘xxx.xxx.psu.ac.th’,
    ),
    ‘datadirectory’ => ‘/var/www/owncloud/data’,
    ‘overwrite.cli.url’ => ‘https://xxx.xxx.psu.ac.th/owncloud’,
    ‘dbtype’ => ‘mysql’,
    ‘version’ => ‘8.0.2.0’,
    ‘dbname’ => ‘owncloud_db’,
    ‘dbhost’ => ‘localhost’,
    ‘dbtableprefix’ => ‘oc_’,
    ‘dbuser’ => ‘xxxxx’,
    ‘dbpassword’ => ‘xxxxx’,
    ‘installed’ => true,
    ‘ldapIgnoreNamingRules’ => false,
    ‘theme’ => ”,
    ‘maintenance’ => false,
    ‘mail_smtpmode’ => ‘smtp’,

    /// AD LDAP ///
    ‘user_backends’ => array(
    0 => array(
    ‘class’ => ‘OC_User_ADLDAP’,
    ‘arguments’ => array(
    0 => ‘dc7.psu.ac.th’,
    ),
    ),
    ),
    /// END ///
    );

     

    4.เพิ่ม code โดยเข้าไปที่ไฟล์ /var/www/owncloud/apps/user_external/appinfo/app.php ไว้บรรทัดล่างสุด

    OC::$CLASSPATH[‘OC_User_ADLDAP’]=’user_external/lib/adldap.php’;

    เมื่อเพิ่มแล้วจะได้ตามนี้

    <?php
    OC::$CLASSPATH[‘OC_User_IMAP’]=’user_external/lib/imap.php’;
    OC::$CLASSPATH[‘OC_User_SMB’]=’user_external/lib/smb.php’;
    OC::$CLASSPATH[‘OC_User_FTP’]=’user_external/lib/ftp.php’;
    OC::$CLASSPATH[‘OC_User_ADLDAP’]=’user_external/lib/adldap.php’;

     

    5. สร้างไฟล์ชื่อ adldap.php นำไปไว้ที่ /var/www/owncloud/apps/user_external/lib/
    จากนั้นให้ทำการเพิ่ม code เข้าไปดังนี้

    หมายเหตุ สำหรับท่านใดที่นำไปใช้งาน ก่อนวันที่ 10-04-58 ขอให้ copy php code ทั้งหมดไปแทนของเดิมด้วยนะครับ

    <?php
    /*
    | ——————————————————————————
    | Owncloud 8 Authentication With ADLDAP 
    | ——————————————————————————
    |
    | Create Date : 08-04-2015
    | Update : 18-10-2016

    | Developer : Aussadayut Ubonkan
    | e-mail : aussadayut.u@psu.ac.th
    | Khunying Long Athakravisunthorn Learning Resources Center, Prince of Songkla University
    |
    */
    require_once(‘3rdparty/adldap/src/adLDAP.php’);

    class OC_User_ADLDAP extends \OCA\user_external\Base{

    private $ad_ldap;

    public $authUser = NULL;
    public $user_authen = NULL;
    public $port = NULL;
    public $basedn = NULL;
    public $ssl = NULL;
    public $account_suffix = NULL;
    public $attribute_mapping = NULL;
    public $addgroup = NULL;
    public $departid = NULL;
    public $set_quota = NULL;


    public function checkPassword($uid,$password){

    $this->set_quota = ‘5 GB’; // Ex. ’12 GB’ , ‘100 MB’
    $this->addgroup = ‘Staffs’; // Group Name
    $this->departid = ‘294’; // Department id , 294 = clib psu

    $this->port = ‘636’; // ldap = 389 , ldaps = 636
    $this->basedn = ‘dc=psu,dc=ac,dc=th’;
    $this->ssl = true;
    $this->account_suffix = ‘@psu.ac.th’;
    $this->attribute_mapping = array(
    “cn”, “dn”, “samaccountname”, “employeeid”, “citizenid”, “company”,
    “campusid”, “department”, “departmentid”, “physicaldeliveryofficename”, “positionid”,
    “description”, “displayname”, “title”, “personaltitle”, “personaltitleid”, “givenname”,
    “sn”, “sex”, “userprincipalname”,”mail”);

    $this->ad_ldap = new adLDAP(
    array(
    ‘domain_controllers’ => array(‘dc7.psu.ac.th’,’dc5.psu.ac.th’),
    ‘ad_port’ => $this->port,
    ‘base_dn’ => $this->basedn,
    ‘use_ssl’ => $this->ssl,
    ‘account_suffix’ => $this->account_suffix,
    )
    );

     

    $this->authUser = $this->ad_ldap->user()->authenticate($uid , $password);
    $this->user_authen = $this->ad_ldap->user()->info($uid,$this->attribute_mapping);

    $check_departid = $this->user_authen[0][“departmentid”][0]; // department id
    $uid = $this->user_authen[0][“samaccountname”][0]; // username
    $uemail = $this->user_authen[0][“userprincipalname”][0]; // e-mail

    /*
    | Print User information
    */
    //echo “<pre>”;
    //print_r($this->user_authen);
    //exit;
    if($check_departid == $this->departid){

    if(!$this->user_Exists($uid)){

    $this->storeUser($uid);

    OC_Group::addToGroup($uid, $this->addgroup); // Add User to Group
    OC_DB::executeAudited(
    ‘INSERT INTO `*PREFIX*preferences` ( `userid`, `appid` , `configkey` ,`configvalue`)’
    . ‘ VALUES( ?, ? , ? ,?)’,
    array($uid, ‘files’, ‘quota’ , $this->set_quota)
    );
    OC_DB::executeAudited(
    ‘INSERT INTO `*PREFIX*preferences` ( `userid`, `appid` , `configkey` ,`configvalue`)’
    . ‘ VALUES( ?, ? , ? ,?)’,
    //array($uid, ‘files’, ‘quota’ , $this->set_quota),
    array($uid, ‘settings’, ’email’ , $uemail)
    ); // Set E-Mail

    return $uid;

    }else{

    $this->storeUser($uid);
    return $uid;
    }
    }else{

    return false;

    }

    } // End checkPassword
    public function user_Exists($uid) {
    $result = OC_DB::executeAudited(
    ‘SELECT COUNT(*) FROM `*PREFIX*users_external`’
    . ‘ WHERE LOWER(`uid`) = LOWER(?)’,
    array($uid)
    );
    return $result->fetchOne() > 0;
    } // user_Exists
    } // End extends \OCA\user_external\Base

    ในที่นี้ขออธิบายเพิ่มเติมสำหรับ adldap.php แค่ 4 ส่วน คือ

    สวนที่ 1. require_once(‘3rdparty/adldap/src/adLDAP.php’);  เส้นทางที่ใช้อ้างอิงไฟล์ ADLdap (PHP Libray) เพื่อนำมาใช้ร่วมกับ owncloud

    สวนที่ 2. $this->set_quota = ‘5 GB’;  กำหนดเนื้อที่เริ่มต้นของของผู้ใช้งาน

    ส่วนที่ 3. $this->addgroup = ‘Staffs’;  ใส่ชื่อกลุ่มที่ต้องการ เพื่อใช้สำหรับเพิ่มกลุ่มให้กับผู้ใช้งานโดยอัตโนมัติ
    เงื่อนไข จะต้องการสร้างชื่อกลุ่มไว้ก่อนจึงจะใช้งานได้ โดยเข้าไปที่เมนู Admin จากนั้นกดเมนูด้านซ้าย Add Group แล้วใส่ชื่อกลุ่มที่ต้องการ จากนั้นกด ปุ่ม +

    ส่วนที่ 4. $this->departid = ‘294’; กำหนดหมายเลขของหน่วยงาน เพื่อใช้กรองว่าต้องการให้หน่วนงานใด สามารถเข้าสู่ระบบมาใช้งานได้ ในที่นี้ 294 คือ หมายเลขของห้องสมุดครับ

    ผลลัพธ์ที่เกิดขึ้น
    เมื่อติดตั้งตามขั้นตอนดังกล่าวครบแล้วนั้น เมื่อมีการเข้าระบบ owncloud ด้วย psu passport หากเป็นบุคลากร ของคณะ/หน่วยงาน ตามหมายเลขกำหนด ก็จะสามารถเข้ามาใช้งานได้และ username นั้น ก็จะถูกเพิ่มเข้าไปในกลุ่มที่กำหนดโดยอัตโนมัติ ครับ

    ขอขอบคุณทุกท่าน ที่อ่านมาถึงตรงนี้ครับ 

    ^_^

  • วิธีการติดตั้ง CA Certificate PSU Passport บน Ubuntu Server

    ทดสอบบน : Ubuntu 14.04

    ขั้นตอนการติดตั้ง Certificate บนเครื่อง Ubuntu Server

    1. เข้า Web Site : https://ca.psu.ac.th ทำการ Login ด้วย Account PSU Passport

    2. ให้เลือกหัวข้อ Download a CA Certificate….. ดังรูป1

    3. ในหน้าต่าง Download a CA Certificate ให้ทำการ Download ไฟล์ดังรูป (เลือกดี ๆ นะครับ เลือก Base 64 ไม่ใช่ DER)2015-01-27_153731

    4. เมื่อโหลดแล้วจะได้ไฟล์ดังรูป3

    5. เมื่อดูข้อความในไฟล์จะได้ประมาณรูปนี้ (ที่เป็นแถบขาว คือ Sensor ครับ :P)2015-01-27_153759

    6. ทำการ copy ข้อความในไฟล์ certificate ไปยัง folder เก็บ certificate ดังนี้

    sudo sh -c 'cat certnew.cer > /etc/ssl/certs/psucer.crt'
    

    7. ทำการแก้ไขไฟล์ /etc/ldap/ldap.conf ดังนี้

    #TLS_CACERT /etc/ssl/certs/ca-certificates.crt
    TLS_CACERT /etc/ssl/certs/psucer.crt
    

    *หมายเหตุ จริง ๆ แล้วมีอีกวิธีคือข้ามการ Check Certificate ไปเลย โดยจะเพิ่มข้อความ TLS_REQCERT never ท้ายไฟล์ /etc/ldap/ldap.conf ก็ได้ดังนี้

    sudo sh -c 'echo "TLS_REQCERT never" >> /etc/ldap/ldap.conf'

    แต่วิธีนี้อาจจะไม่ปลอดภัยครับ เพราะอาจเจอ phising site ที่ปลอม server เข้ามาสวมรอยได้ครับ เพราะไม่ได้มีการ verify certificate ว่า server เป็นตัวจริง