|

หน้าจอการทำ Login เข้าไปยัง Google Sheet เพื่อทำการตรวจสอบสิทธิในการใช้งาน และบันทึกค่า GUID ...

Add References ... ต้องติดตั้ง Library เข้าไปใหม่ด้วยครับ ...
คลิปวิดีโอในการใช้งาน Nuget เพื่อทำการติดตั้ง Google API และ Material Skin.2 ... *****

ข้อมูลตัวอย่างใน Google Sheet ...
คลิปวิดีโอในการสร้างและใช้งาน Google App Script ... *****
โค้ด VB.NET กับการตรวจสอบการ Login เข้าใช้งานโปรแกรมได้เพียงครั้งละ 1 เครื่อง ด้วยการใช้ GUID ผ่านทาง Google Sheet ทำงานร่วมกับ Google App Script
GUID (Globally Unique IDentifier) คือ "รหัสเฉพาะที่ไม่ซ้ำกันเลยในระดับโลก" ซึ่งใช้เพื่อระบุสิ่งใดสิ่งหนึ่งแบบเฉพาะเจาะจง เช่น:
- อุปกรณ์แต่ละเครื่อง (เช่น PC, มือถือ)
- ไฟล์, เอกสาร, บันทึกในฐานข้อมูล
- ผู้ใช้ หรือ session ในระบบ
GUID มีความยาว 128 บิต และมักแสดงในรูปแบบข้อความ เช่น 6c483b5b-a74b-4fca-be14-6781b30c6b58
มาดูส่วนของ Google App Script เพื่อทำการอ่านเขียนข้อมูล GUID ลงไปใน Google Sheet ... หาก Google Sheet มีการเปลี่ยนแปลงหลัก (Column) ต้องปรับแต่งค่าตามไปด้วย ...
- function doPost(e) {
- const ss = SpreadsheetApp.openById("SpreadSheetID"); // ต้องเปลี่ยนค่านี้ตาม Sheet ที่ใช้งานด้วย
- const sheet = ss.getSheetByName("UserLogin"); // ชื่อ SheetName ต้องเปลี่ยนด้วย
- if (!sheet) {
- return ContentService.createTextOutput("Error: Sheet not found");
- }
- const action = e.parameter.action;
- const username = e.parameter.username;
- const guid = e.parameter.guid;
- const timestamp = e.parameter.timestamp;
- if (action === "update_guid") {
- let range = sheet.getDataRange();
- let values = range.getValues();
- for (let i = 1; i < values.length; i++) { // เริ่มที่ 1 เพราะแถว 0 คือ header
- if (values[i][1] === username) { // Username = คอลัมน์ B
- sheet.getRange(i + 1, 5).setValue(guid); // GUID = คอลัมน์ E
- sheet.getRange(i + 1, 6).setValue(timestamp); // Last Ping = คอลัมน์ F
- return ContentService.createTextOutput("GUID Updated");
- }
- }
- } else if (action === "clear_guid") {
- let range = sheet.getDataRange();
- let values = range.getValues();
- for (let i = 1; i < values.length; i++) {
- if (values[i][4] === guid) { // GUID = คอลัมน์ E
- sheet.getRange(i + 1, 5).setValue(""); // ล้าง GUID
- sheet.getRange(i + 1, 6).setValue(""); // ล้าง Last Ping
- return ContentService.createTextOutput("GUID Cleared");
- }
- }
- }
- return ContentService.createTextOutput("Invalid Request");
- }
คัดลอกไปที่คลิปบอร์ด
มาดูโค้ดฉบับเต็มกันเถอะ ...
- Imports System.Collections.Specialized
- Imports System.IO
- Imports System.Net
- '// Download MaterialSkin.2 packages.
- '// https://www.nuget.org/packages/MaterialSkin.2/
- Imports MaterialSkin
- Imports Microsoft.Win32
- Imports Newtonsoft.Json
- '// คลิปวิดีโอการรับไฟล์ Credentials เพื่อทำการติดต่อกับ Google Sheets และการกำหนดสิทธิ์การเข้าถึง
- '// https://www.youtube.com/watch?v=xdYsctNAGEE
- '// คลิปวิดีโอการติดตั้ง Google API และ Material Skin.2
- '// https://youtu.be/HqNffWxQKaM
- '// คลิปวิดีโอการสร้างและใช้งาน Google App Script
- '// https://youtu.be/X1pCwJJ9VpI
- '// ------------------------------------------------------------------------------------------------
- '// Google Visualization API Reference ... https://developers.google.com/chart/interactive/docs/reference
- '// Google Visualization API
- '// เป็น API จาก Google ที่ช่วยให้เราสามารถดึงข้อมูลจากแหล่งข้อมูลต่างๆ เช่น Google Sheets หรือไฟล์ข้อมูลอื่นๆ
- '// แล้วนำข้อมูลนั้นมา แสดงผลในรูปแบบกราฟ, ตาราง หรือ Visualization ต่างๆบนเว็บได้ง่ายๆ
- '// เหมาะสำหรับการสร้างแดชบอร์ด หรือรายงานแบบ Interactive ที่ทำงานบนเว็บ
- '// Google Visualization API มีฟอร์แมตข้อมูลเฉพาะที่เรียกว่า DataTable (เหมือนตารางฐานข้อมูล มีคอลัมน์และแถว)
- '// เราสามารถดึงข้อมูลผ่าน URL โดยใช้ Google Visualization Query Language (GVQL) ซึ่งคล้าย SQL
- '// ------------------------------------------------------------------------------------------------
- Public Class frmLogin
- '// ป้อน Spreadsheet ID และชื่อชีต
- Private ReadOnly SpreadsheetId As String = "SPREAD_SHEET_ID" '// อย่าลืมใส่ค่าของคุณด้วย
- 'Private ReadOnly ApplicationName As String = "" '// ไม่ได้ใช้งาน
- Private ReadOnly SheetName As String = "SHEET_NAME" '// อย่าลืมใส่ค่าของคุณด้วย
- Dim CurrentUsername As String = String.Empty
- Dim MyGuid As String = GetMachineGuid()
- Dim WithEvents Timer1 As New Timer()
- Private Sub frmLogin_Load(sender As Object, e As EventArgs) Handles MyBase.Load
- '// ข้อมูลตัวอย่าง
- txtUserName.Text = "admin"
- txtPassword.Text = "admin"
- With Me
- .MinimumSize = New Point(451, 503)
- .MaximumSize = New Point(451, 503)
- End With
- '// Code sample.
- '// https://www.nuget.org/packages/MaterialSkin.2/
- Dim SkinManager As MaterialSkinManager = MaterialSkinManager.Instance
- SkinManager.AddFormToManage(Me)
- SkinManager.Theme = MaterialSkinManager.Themes.DARK
- SkinManager.ColorScheme = New ColorScheme(Primary.Amber500, Primary.BlueGrey900, Primary.BlueGrey500, Accent.LightBlue200, TextShade.WHITE)
- '// ตัวอย่างของ ColorScheme
- 'SkinManager.ColorScheme = New ColorScheme(Primary.Blue300, Primary.Blue500, Primary.Blue500, Accent.Blue400, TextShade.WHITE)
- 'SkinManager.ColorScheme = New ColorScheme(Primary.Green600, Primary.Green700, Primary.Green200, Accent.Red100, TextShade.WHITE)
- 'SkinManager.ColorScheme = New ColorScheme(Primary.LightBlue600, Primary.LightBlue700, Primary.Green200, Accent.LightGreen700, TextShade.WHITE)
- 'SkinManager.ColorScheme = New ColorScheme(Primary.Cyan500, Primary.Cyan700, Primary.Cyan100, Accent.Blue100, TextShade.WHITE)
- End Sub
- Private Sub swPassword_CheckedChanged(sender As Object, e As EventArgs) Handles swPassword.CheckedChanged
- txtPassword.Focus()
- txtPassword.Password = Not swPassword.Checked
- End Sub
- '// ------------------------------------------------------------------------------------------------
- '// เริ่มต้นการเข้าสู่ระบบ
- '// ------------------------------------------------------------------------------------------------
- Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
- Dim UserName As String = txtUserName.Text.Trim()
- Dim Password As String = txtPassword.Text.Trim()
- If String.IsNullOrEmpty(UserName) OrElse String.IsNullOrEmpty(Password) Then
- MessageBox.Show("กรุณากรอก Username และ Password", "แจ้งเตือน", MessageBoxButtons.OK, MessageBoxIcon.Warning)
- Return
- End If
- '//
- '// ใช้ Google Visualization API เพื่อดึงข้อมูลทั้งหมด
- Dim JsonRaw As String = New WebClient().DownloadString("https://docs.google.com/spreadsheets/d/" & SpreadsheetId & "/gviz/tq?tqx=out:json&sheet=" & SheetName)
- '// ตัดข้อความส่วนหน้าและท้ายออก
- Dim jsonClean As String = JsonRaw
- If jsonClean.StartsWith("/*O_o*/") Then
- Dim startIndex = jsonClean.IndexOf("{")
- Dim endIndex = jsonClean.LastIndexOf("}")
- jsonClean = jsonClean.Substring(startIndex, endIndex - startIndex + 1)
- End If
- '// แปลง JSON
- Dim result = JsonConvert.DeserializeObject(Of GoogleSheetResponse)(jsonClean)
- For Each row In result.table.rows
- Dim uid = row.c(1)?.v?.ToString()
- Dim pwd = row.c(2)?.v?.ToString()
- Dim expireRaw = row.c(3)?.f '// ใช้ .f เพื่ออ่านแบบ dd/MM/yyyy
- Dim storedGuid = row.c(4)?.v?.ToString()
- Dim lastPingStr = row.c(5)?.v?.ToString()
- '// ตรวจสอบ Username และ Password
- If UserName = uid AndAlso Password = pwd Then
- Dim expireDate As DateTime
- If DateTime.TryParseExact(expireRaw, "dd/MM/yyyy", New Globalization.CultureInfo("th-TH"), Globalization.DateTimeStyles.None, expireDate) Then
- If expireDate.Year > 2500 Then expireDate = expireDate.AddYears(-543)
- '// ตรวจสอบวันที่หมดอายุการใช้งานโปรแกรม
- If Date.Today > expireDate Then
- MessageBox.Show("บัญชีหมดอายุ กรุณาติดต่อผู้ดูแลระบบ", "Report Error", MessageBoxButtons.OK, MessageBoxIcon.Stop)
- Exit Sub
- End If
- '// ตรวจสอบ GUID
- If String.IsNullOrWhiteSpace(storedGuid) OrElse storedGuid = MyGuid Then
- MessageBox.Show("เข้าสู่ระบบสำเร็จ!", "Report Status", MessageBoxButtons.OK, MessageBoxIcon.Information)
- CurrentUsername = txtUserName.Text.Trim '// <-- เก็บชื่อผู้ใช้จริงที่ล็อกอินสำเร็จ
- Call StartPingTimer() '// เริ่มจับเวลา
- Call WriteGuid(MyGuid)
- frmMain.Show()
- Me.Hide()
- Return
- Else
- MessageBox.Show("บัญชีนี้ถูกล็อกไว้ที่เครื่องอื่น!!!", "Report Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
- Exit Sub
- End If
- End If
- End If
- Next
- MessageBox.Show("Username หรือ Password ไม่ถูกต้อง!!!", "Report Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
- End Sub
- '// ------------------------------------------------------------------------------------------------
- Sub StartPingTimer()
- Timer1.Interval = 60000 '// 60 วินาที (1 วินาที = 1000 มิลลิวินาที (ms))
- Timer1.Start()
- End Sub
- '// ------------------------------------------------------------------------------------------------
- Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
- WriteGuid(MyGuid)
- End Sub
- '// ------------------------------------------------------------------------------------------------
- '// การเขียนข้อมูล GUID ลงไปใน Google Sheet เมื่อเริ่มต้นทำงานของโปรแกรม
- '// ------------------------------------------------------------------------------------------------
- Sub WriteGuid(guid As String)
- Dim url = "ใส่ค่า URL ที่ได้จาก App Script"
- '// Google Apps Script endpoint
- Dim data As New NameValueCollection()
- data("action") = "update_guid"
- data("username") = CurrentUsername
- data("guid") = guid
- '// วันที่และเวลาแบบ UTC (Coordinated Universal Time) ซึ่งเป็นเวลามาตรฐานโลก ไม่ขึ้นอยู่กับโซนเวลา (Time Zone) ของเครื่องคอมพิวเตอร์
- '// เวลาท้องถิ่นประเทศไทย จะ +7 ทำให้เวลาของไทยจะเร็วกว่าและต่างกับเวลามาตรฐานไป 7 ชั่วโมง
- data("timestamp") = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss")
- '// หรือจะใช้เวลาท้องถิ่นของเครื่อง (Local Time) แทน DateTime.UtcNow
- 'DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture)
- '//
- Using client As New WebClient()
- Try
- Dim response = client.UploadValues(url, "POST", data)
- 'MessageBox.Show(Encoding.UTF8.GetString(response))
- '// ดูการตอบสนองหากมี Error อื่นๆ เช่น การเชื่อมต่อเน็ตอยู่หรือไม่
- Catch ex As WebException
- MessageBox.Show("Error: " & ex.Message)
- If ex.Response IsNot Nothing Then
- '// ลองทดสอบการตัดอินเทอร์เน็ตดูครับ
- Using reader As New StreamReader(ex.Response.GetResponseStream())
- MessageBox.Show("Detail: " & reader.ReadToEnd())
- End Using
- End If
- End Try
- End Using
- End Sub
- Private Sub frmLogin_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
- '// เมื่อปิดโปรแกรมก็ทำการเคลียร์ค่า GUID
- ClearGuid(MyGuid)
- End Sub
- '// ------------------------------------------------------------------------------------------------
- '// การเคลียร์ค่า GUID ใน Google Sheet หลังจากการปิดโปรแกรม
- '// ------------------------------------------------------------------------------------------------
- Sub ClearGuid(guid As String)
- Dim url = "ใส่ค่า URL ที่ได้จาก App Script"
- Dim data As New NameValueCollection()
- data("action") = "clear_guid"
- data("guid") = guid
- Using client As New WebClient()
- client.UploadValues(url, "POST", data)
- End Using
- End Sub
- '// ------------------------------------------------------------------------------------------------
- '// อ่านค่า GUID เครื่องตามขนาดจำนวนบิตของระบบปฏิบัติการ
- '// ------------------------------------------------------------------------------------------------
- Function GetMachineGuid() As String
- Try
- '// ตรวจสอบว่า OS เป็นแบบ 64-bit หรือไม่
- Dim view As RegistryView = If(Environment.Is64BitOperatingSystem, RegistryView.Registry64, RegistryView.Registry32)
- '// เปิด Registry ตามขนาดของ OS
- Dim baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, view)
- Dim key = baseKey.OpenSubKey("SOFTWARE\Microsoft\Cryptography")
- If key IsNot Nothing Then
- Dim machineGuid = key.GetValue("MachineGuid")?.ToString()
- If Not String.IsNullOrWhiteSpace(machineGuid) Then Return machineGuid
- End If
- Catch ex As Exception
- MessageBox.Show("Error reading MachineGuid: " & ex.Message, "Registry Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
- End Try
- Return Nothing
- End Function
- Private Sub txtUserName_KeyPress(sender As Object, e As KeyPressEventArgs) Handles txtUserName.KeyPress
- '// Press ENTER
- If Asc(e.KeyChar) = 13 Then
- e.Handled = True '// No beep
- SendKeys.Send("{TAB}")
- End If
- End Sub
- Private Sub txtPassword_KeyPress(sender As Object, e As KeyPressEventArgs) Handles txtPassword.KeyPress
- '// Press ENTER
- If Asc(e.KeyChar) = 13 Then
- e.Handled = True '// No beep
- SendKeys.Send("{TAB}")
- End If
- End Sub
- Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
- Me.Close()
- End Sub
- Private Sub frmLogin_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
- Me.Dispose()
- GC.SuppressFinalize(Me)
- Application.Exit()
- End Sub
- End Class
คัดลอกไปที่คลิปบอร์ด
ดาวน์โหลดโค้ดต้นฉบับ VB.NET & .Net Framework 4.6.2+ ได้ที่นี่ ...
|
ขออภัย! โพสต์นี้มีไฟล์แนบหรือรูปภาพที่ไม่ได้รับอนุญาตให้คุณเข้าถึง
คุณจำเป็นต้อง ลงชื่อเข้าใช้ เพื่อดาวน์โหลดหรือดูไฟล์แนบนี้ คุณยังไม่มีบัญชีใช่ไหม? ลงทะเบียน
x
|