ginvalidator ialah satu set middleware Gin yang membungkus koleksi luas pengesah dan sanitizer yang ditawarkan oleh validatorgo pakej sumber terbuka saya yang lain. Ia juga menggunakan pakej sumber terbuka yang popular gjson untuk sintaks medan JSON, menyediakan pertanyaan dan pengekstrakan data yang cekap daripada objek JSON.
Ia membolehkan anda menggabungkannya dalam pelbagai cara supaya anda boleh mengesahkan dan membersihkan permintaan Gin anda, serta menawarkan alatan untuk menentukan sama ada permintaan itu sah atau tidak, data yang dipadankan mengikut pengesah anda.
Ia berdasarkan pengesah ekspres perpustakaan js/express popular
Versi ginvalidator ini memerlukan aplikasi anda dijalankan pada Go 1.16 .
Ia juga disahkan untuk berfungsi dengan Gin 1.x.x.
Mengapa tidak menggunakan?
Pastikan anda telah memasang Go pada mesin anda.
go mod init example.com/learning
Gunakan go get untuk memasang pakej yang diperlukan.
go get -u github.com/gin-gonic/gin
go get -u github.com/bube054/ginvalidator
Salah satu cara terbaik untuk mempelajari sesuatu adalah melalui teladan! Jadi mari kita singsingkan lengan baju dan dapatkan beberapa pengekodan berlaku.
Perkara pertama yang diperlukan ialah pelayan Gin sedang berjalan. Mari kita laksanakan yang mengucapkan hai kepada seseorang; untuk ini, buat main.go kemudian tambah kod berikut:
package main import ( "net/http" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/hello", func(ctx *gin.Context) { person := ctx.Query("person") ctx.String(http.StatusOK, "Hello, %s!", person) }) r.Run() // listen and serve on 0.0.0.0:8080 }
Sekarang jalankan fail ini dengan melaksanakan go run main.go pada terminal anda.
go mod init example.com/learning
Pelayan HTTP sepatutnya berjalan dan anda boleh membuka http://localhost:8080/hello?person=John untuk memberi hormat kepada John!
? Petua:
Anda boleh menggunakan Air dengan Go dan Gin untuk melaksanakan tambah nilai secara langsung. Ini secara automatik memulakan semula pelayan apabila fail ditukar, jadi anda tidak perlu melakukannya sendiri!
Jadi pelayan berfungsi, tetapi terdapat masalah dengannya. Paling ketara, anda tidak mahu bertanya khabar kepada seseorang apabila nama orang itu tidak ditetapkan.
Contohnya, pergi ke http://localhost:8080/hello akan mencetak "Hello, ".
Di situlah ginvalidator berguna. Ia menyediakan pengesah, sanitizer dan pengubah suai yang digunakan untuk mengesahkan permintaan anda.
Mari tambahkan pengesah dan pengubah suai yang menyemak bahawa rentetan pertanyaan orang tidak boleh kosong, dengan pengesah bernama Kosong dan pengubah bernama Not:
go get -u github.com/gin-gonic/gin
? Nota:
Untuk ringkasnya, gv digunakan sebagai alias untuk ginvalidator dalam contoh kod.
Sekarang, mulakan semula pelayan anda dan pergi ke http://localhost:8080/hello sekali lagi. Hmm, masih tertera "Hello, !"... kenapa?
rantaian pengesahan ginvalidator tidak melaporkan ralat pengesahan kepada pengguna secara automatik.
Sebabnya adalah mudah: semasa anda menambah lebih banyak pengesah, atau untuk lebih banyak medan, bagaimana anda mahu mengumpul ralat? Adakah anda mahu senarai semua ralat, hanya satu setiap medan, hanya satu keseluruhan...?
Jadi langkah seterusnya yang jelas ialah menukar kod di atas sekali lagi, kali ini mengesahkan hasil pengesahan dengan fungsi ValidationResult:
go get -u github.com/bube054/ginvalidator
Sekarang, jika anda mengakses http://localhost:8080/hello sekali lagi, anda akan melihat kandungan JSON berikut, diformatkan untuk kejelasan:
package main import ( "net/http" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/hello", func(ctx *gin.Context) { person := ctx.Query("person") ctx.String(http.StatusOK, "Hello, %s!", person) }) r.Run() // listen and serve on 0.0.0.0:8080 }
Sekarang, perkara ini memberitahu kami ialah
Ini adalah senario yang lebih baik, tetapi ia masih boleh diperbaiki. Jom teruskan.
Semua pengesah lokasi permintaan menerima hujah kedua pilihan, iaitu fungsi yang digunakan untuk memformat mesej ralat. Jika tiada disediakan, mesej ralat generik lalai akan digunakan, seperti yang ditunjukkan dalam contoh di atas.
go run main.go
Sekarang jika anda mengakses http://localhost:8080/hello sekali lagi, perkara yang anda akan lihat ialah kandungan JSON berikut, dengan mesej ralat baharu:
package main import ( "net/http" gv "github.com/bube054/ginvalidator" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/hello", gv.NewQuery("person", nil). Chain(). Not(). Empty(nil). Validate(), func(ctx *gin.Context) { person := ctx.Query("person") ctx.String(http.StatusOK, "Hello, %s!", person) }) r.Run() }
Anda boleh menggunakan GetMatchedData, yang secara automatik mengumpulkan semua data yang telah disahkan dan/atau dibersihkan oleh ginvalidator. Data ini kemudiannya boleh diakses menggunakan kaedah Dapatkan MatchedData:
go mod init example.com/learning
buka http://localhost:8080/hello?person=John untuk memberi hormat kepada John!
Lokasi yang tersedia ialah BodyLocation, CookieLocation QueryLocation, ParamLocation dan HeaderLocation.
Setiap lokasi ini termasuk kaedah Rentetan yang mengembalikan lokasi tempat data yang disahkan/disanitasi disimpan.
Walaupun pengguna tidak lagi boleh menghantar nama orang kosong, ia masih boleh menyuntik HTML ke halaman anda! Ini dikenali sebagai kerentanan Skrip Silang Tapak (XSS).
Mari lihat bagaimana ia berfungsi. Pergi ke http://localhost:8080/hello?person=John, dan anda seharusnya melihat "Hello, John!".
Walaupun contoh ini baik, penyerang boleh menukar rentetan pertanyaan orang kepada
Dalam senario ini, satu cara untuk mengurangkan isu dengan ginvalidator ialah menggunakan sanitizer, terutamanya Escape, yang mengubah aksara HTML khas dengan yang lain yang boleh diwakili sebagai teks.
go get -u github.com/gin-gonic/gin
Sekarang, jika anda memulakan semula pelayan dan memuat semula halaman, perkara yang anda akan lihat ialah "Helo, John!". Halaman contoh kami tidak lagi terdedah kepada XSS!
⚠️ Awas:
ginvalidator tidak mengubah suai http.Minta nilai semasa sanitasi. Untuk mengakses data yang telah dibersihkan, sentiasa gunakan fungsi GetMatchedData.
Rantai pengesahan ialah salah satu konsep utama dalam ginvalidator, oleh itu adalah berguna untuk mempelajarinya, supaya anda boleh menggunakannya dengan berkesan.
Tetapi jangan risau: jika anda telah membaca panduan Bermula, anda telah menggunakan rantaian pengesahan tanpa perasan!
Rantai pengesahan dibuat menggunakan fungsi berikut, setiap satu menyasarkan lokasi tertentu dalam permintaan HTTP:
Mereka mempunyai nama ini kerana mereka membungkus nilai medan dengan pengesahan (atau sanitasi), dan setiap kaedahnya mengembalikan dirinya sendiri.
Corak ini biasanya dipanggil kaedah rantaian, oleh itu mengapa nama rantai pengesahan.
Rantai pengesahan bukan sahaja mempunyai beberapa kaedah berguna untuk mentakrifkan pengesahan, sanitasi dan pengubahsuaian tetapi ia juga mempunyai kaedah Validate yang mengembalikan fungsi pengendali middleware Gin.
Ini ialah contoh cara rantaian pengesahan biasanya digunakan dan cara anda boleh membacanya:
go mod init example.com/learning
Rantai pengesahan mempunyai tiga jenis kaedah: pengesah, sanitizer dan pengubah suai.
Pengesah menentukan sama ada nilai medan permintaan adalah sah. Ini bermakna menyemak sama ada medan itu dalam format yang anda harapkan. Contohnya, jika anda sedang membina borang pendaftaran, keperluan anda mungkin nama pengguna mestilah alamat e-mel dan kata laluan mestilah sekurang-kurangnya 8 aksara.
Jika nilai tidak sah, ralat direkodkan untuk medan tersebut menggunakan beberapa mesej ralat. Ralat pengesahan ini kemudiannya boleh diambil pada titik kemudian dalam pengendali laluan Gin dan dikembalikan kepada pengguna.
Mereka ialah:
Sanitizer mengubah nilai medan. Ia berguna untuk menghilangkan bunyi daripada nilai dan mungkin juga untuk menyediakan beberapa garis pertahanan asas terhadap ancaman.
Sanitizer mengekalkan nilai medan yang dikemas kini kembali ke dalam Konteks Gin, supaya ia boleh digunakan oleh fungsi ginvalidator lain, kod pengendali laluan anda sendiri dan juga middleware lain.
Mereka ialah:
Pengubah suai mentakrifkan bagaimana rantaian pengesahan bertindak apabila ia dijalankan.
Mereka ialah:
? Nota:
Kaedah ini didokumenkan dengan teliti menggunakan GoDoc dalam dokumentasi ginvalidator pkg.go.dev. Jika sebarang butiran tidak jelas, anda juga boleh merujuk kepada fungsi berkaitan dalam pakej validatorgo untuk konteks tambahan, yang akan saya jelaskan di bawah.
Semua fungsi yang didedahkan oleh rantaian pengesahan sebenarnya berasal daripada validatorgo, salah satu pakej sumber terbuka saya yang lain yang mengkhusus dalam pengesahan/sanitasi rentetan. Sila semaknya, bintang dan kongsi ???, Terima Kasih.
Ini termasuk semua validatorgo validator dan sanitizer, daripada IsEmail, IsLength dan Trim yang biasa digunakan kepada IsISBN, IsMultibait dan StripLow yang lebih khusus!
Ini dipanggil pengesah standard dan sanitizer standard dalam ginvalidator. Tetapi tanpa awalan Is daripada validatorgo.
Tertib anda memanggil kaedah pada rantaian pengesahan biasanya penting.
Ia hampir selalu dijalankan mengikut tertib yang ditentukan, oleh itu anda boleh mengetahui perkara yang akan dilakukan oleh rantaian pengesahan hanya dengan membaca definisinya, daripada kaedah berantai pertama hingga terakhir.
Ambil coretan berikut sebagai contoh:
go mod init example.com/learning
Dalam kes ini, jika pengguna memberikan nilai "search_query" yang terdiri daripada ruang putih sahaja, nilai itu tidak akan kosong, oleh itu pengesahan lulus. Tetapi memandangkan sanitizer .Trim() ada, ruang putih akan dialih keluar dan medan akan menjadi kosong, jadi anda sebenarnya mendapat positif palsu.
Sekarang, bandingkan dengan coretan di bawah:
go get -u github.com/gin-gonic/gin
Rantaian ini akan mengalih keluar ruang putih dengan lebih bijak, dan kemudian mengesahkan jika nilainya tidak kosong.
Satu pengecualian kepada peraturan ini ialah .Optional(): Ia boleh diletakkan pada mana-mana titik dalam rantai dan ia akan menandakan rantai sebagai pilihan.
Jika anda ingin menggunakan semula rantai yang sama, adalah idea yang baik untuk mengembalikannya daripada fungsi:
go get -u github.com/bube054/ginvalidator
Dalam ginvalidator, medan ialah sebarang nilai yang sama ada disahkan atau dibersihkan dan ia adalah rentetan.
Hampir hampir setiap fungsi atau nilai yang dikembalikan oleh medan rujukan ginvalidator dalam beberapa cara. Atas sebab ini, adalah penting untuk memahami sintaks laluan medan semasa memilih medan untuk pengesahan dan semasa mengakses ralat pengesahan atau data yang disahkan.
Medan isi hanya sah untuk Jenis Kandungan berikut:
go mod init example.com/learning
Dengan nama pengguna laluan, nilai yang diekstrak ialah "John".
go get -u github.com/gin-gonic/gin
Badan:
go get -u github.com/bube054/ginvalidator
Medan "nama" akan mempunyai nilai "John", dan "e-mel" akan mempunyai nilai "john.doe@example.com".
package main import ( "net/http" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/hello", func(ctx *gin.Context) { person := ctx.Query("person") ctx.String(http.StatusOK, "Hello, %s!", person) }) r.Run() // listen and serve on 0.0.0.0:8080 }
Badan:
go run main.go
Medan "nama" akan mempunyai nilai "John", dan "fail" ialah fail yang dimuat naik.
Medan pertanyaan sepadan dengan parameter carian URL dan nilainya secara automatik tidak dielakkan oleh Gin.
Contoh:
package main import ( "net/http" gv "github.com/bube054/ginvalidator" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/hello", gv.NewQuery("person", nil). Chain(). Not(). Empty(nil). Validate(), func(ctx *gin.Context) { person := ctx.Query("person") ctx.String(http.StatusOK, "Hello, %s!", person) }) r.Run() }
package main import ( "net/http" gv "github.com/bube054/ginvalidator" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/hello", gv.NewQuery("person", nil). Chain(). Not(). Empty(nil). Validate(), func(ctx *gin.Context) { result, err := gv.ValidationResult(ctx) if err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ "message": "The server encountered an unexpected error.", }) return } if len(result) != 0 { ctx.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{ "errors": result, }) return } person := ctx.Query("person") ctx.String(http.StatusOK, "Hello, %s!", person) }) r.Run() }
Medan Param mewakili parameter laluan URL dan nilainya tidak dilepaskan secara automatik oleh ginvalidator.
Contoh:
{ "errors": [ { "location": "queries", "message": "Invalid value", "field": "person", "value": "" } ] }
Medan pengepala ialah pengepala permintaan HTTP dan nilainya tidak terlepas. Amaran log akan muncul jika anda memberikan kunci pengepala bukan kanonik.
Contoh:
package main import ( "net/http" gv "github.com/bube054/ginvalidator" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/hello", gv.NewQuery("person", func(initialValue, sanitizedValue, validatorName string) string { return "Please enter your name." }, ).Chain(). Not(). Empty(nil). Validate(), func(ctx *gin.Context) { result, err := gv.ValidationResult(ctx) if err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ "message": "The server encountered an unexpected error.", }) return } if len(result) != 0 { ctx.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{ "errors": result, }) return } person := ctx.Query("person") ctx.String(http.StatusOK, "Hello, %s!", person) }) r.Run() }
Medan kuki ialah kuki HTTP dan nilainya secara automatik tidak dapat dielakkan oleh Gin.
Contoh:
{ "errors": [ { "location": "queries", "message": "Please enter your name.", "field": "person", "value": "" } ] }
Jika pelayan yang anda bina hanyalah pelayan yang sangat mudah, anda memerlukan pengesah, sanitizer dan mesej ralat selain daripada yang terbina dalam ginvalidator lambat laun.
Keperluan klasik yang tidak dapat dipenuhi oleh ginvalidator untuk anda, dan yang mungkin anda hadapi, adalah mengesahkan sama ada alamat e-mel sedang digunakan atau tidak semasa pengguna mendaftar.
Ini boleh dilakukan dalam ginvalidator dengan melaksanakan pengesah tersuai.
CustomValidator ialah kaedah yang tersedia pada rantaian pengesahan, yang menerima fungsi khas CustomValidatorFunc dan perlu mengembalikan boolean yang akan menentukan sama ada medan itu sah atau tidak.
CustomSanitizer juga merupakan kaedah yang tersedia pada rantaian pengesahan, yang menerima fungsi khas CustomSanitizerFunc, dan perlu mengembalikan nilai bersih yang baharu.
Pengesah Tersuai boleh menjadi tak segerak dengan menggunakan goroutin dan penyegerakan.WaitGroup untuk mengendalikan operasi serentak. Dalam pengesah, anda boleh memutarkan gorout untuk setiap tugas tak segerak, menambah setiap tugas pada WaitGroup. Setelah semua tugasan selesai, pengesah harus mengembalikan boolean.
Sebagai contoh, untuk menyemak sama ada e-mel tidak digunakan:
go mod init example.com/learning
Atau mungkin anda juga boleh mengesahkan bahawa kata laluan sepadan dengan ulangan:
go get -u github.com/gin-gonic/gin
⚠️ Awas:
Jika badan permintaan akan diakses berbilang kali—sama ada dalam rantaian pengesahan yang sama, dalam rantaian pengesahan lain untuk konteks permintaan yang sama atau dalam pengendali seterusnya—pastikan anda menetapkan semula badan permintaan selepas setiap kali dibaca. Kegagalan berbuat demikian boleh menyebabkan ralat atau kehilangan data apabila kandungan dibaca semula.
CustomSanitizer tidak mempunyai banyak peraturan. Walau apa pun nilai yang mereka pulangkan, adalah nilai baharu yang akan diperolehi oleh medan tersebut.
Pembersih tersuai juga boleh tidak segerak dengan menggunakan goroutin dan penyegerakan.WaitGroup untuk mengendalikan operasi serentak.
go get -u github.com/bube054/ginvalidator
Apabila nilai medan tidak sah, mesej ralat direkodkan untuknya.
Mesej ralat lalai ialah "Nilai tidak sah", yang tidak menggambarkan sama sekali tentang ralat itu, jadi anda mungkin perlu menyesuaikannya. Anda boleh menyesuaikan dengan
package main import ( "net/http" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/hello", func(ctx *gin.Context) { person := ctx.Query("person") ctx.String(http.StatusOK, "Hello, %s!", person) }) r.Run() // listen and serve on 0.0.0.0:8080 }
Untuk senarai lengkap nama pengesah, rujuk pemalar ginvalidator.
Atas ialah kandungan terperinci Permudahkan Pengesahan Input Gin dalam Go dengan ginvalidator. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!