.netcore dengan cepat mengakses login pihak ketiga, tanpa penyesalan



Proyek kecil yang saya bawa kali ini adalah komponen login OAuth2. Saya melihat bahwa proyek JustAuth platform Java sangat nyaman untuk mengakses login platform pihak ketiga. Saya merasa gatal. Setelah banyak mencari, saya menemukan bahwa .netcore besar saya dapat digunakan. Ada sedikit, dan kodenya ditulis berantakan, semuanya dalam satu perpustakaan, dan gaya kode tidak dapat diterima, jadi saya memutuskan untuk membuat keputusan, menggunakan keyboard, dan melanjutkan.



Tahun baru itu baru. Memanfaatkan perayaan tahun baru, setelah sepuluh hari, akhirnya saya menerbitkan edisi pertama. Semoga semua menyukainya.


Jika Anda memiliki sepatu anak-anak yang tidak suka membaca teks, Anda dapat langsung melihat alamat berikut untuk mengalami:



https://oauthlogin.net/


Kata pengantar

Proyek kecil yang saya bawa kali ini adalah komponen login OAuth2. Saya melihat bahwa proyek JustAuth di platform Java dapat dengan mudah mengakses platform pihak ketiga untuk login. Saya merasa gatal. Setelah banyak mencari, saya menemukan bahwa .netcore saya yang besar bisa dikatakan kurang berguna. Ada sedikit, dan kodenya ditulis berantakan, semua dalam satu perpustakaan, dan gaya kode tidak digunakan untuk itu, jadi saya memutuskan untuk menggunakan keyboard dan mulai bekerja.


Ada terlalu banyak artikel tentang dasar-dasar dan prinsip-prinsip OAuth2, dan tidak sedikit yang ditulis dengan baik. Saya telah memberikan beberapa tautan di akhir halaman. Jika Anda suka, saya tidak akan menjelaskannya secara mendalam di sini , tapi langsung ke topiknya.


Cara Penggunaan

Berikut adalah demonstrasi mengakses login github, membuat proyek aplikasi Asp.NET Core Web baru, yang disebut GithubLogin (PS: Anda dapat membuat nama yang lebih baik sendiri), memilih pengontrol tampilan model, tentu saja Anda dapat memilih yang lain.


Langkah pertama: instalasi

Instal paket nuget ini:


Instal-Paket MrHuo.OAuth.Github -Version 1.0.0

Langkah 2: Konfigurasi

Buka appsettings.json dan tulis konfigurasi berikut:


{"oauth": {"github": {"app_id": "github_app_id", "app_key": "github_app_key", "redirect_uri": "https://oauthlogin.net/oauth/githubcallback", "scope": " repo "}}}

Konfigurasi di sini dapat didaftarkan melalui https://github.com/settings/applications/new, dan redirect_uri dapat mengisi alamat localhost lokal, yang sangat nyaman, itulah mengapa login github digunakan untuk demonstrasi.




Setelah pembuatan selesai, buat rahasia klien di antarmuka ini:




Masukkan kata sandi dan akan terlihat seperti ini setelah berhasil dibuat:




Isi ID Klien dan rahasia Klien di antarmuka, bersama dengan URL panggilan balik Otorisasi yang diisi di antarmuka sebelumnya, ke posisi yang sesuai dari file konfigurasi. Sekarang file konfigurasi appsettings.json terlihat seperti ini:


{"Logging": {"LogLevel": {"Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information"}}, "AllowedHosts": "*", " oauth ": {" github ": {" app_id ":" c95fxxxxxx0d09 "," app_key ":" c6a73xxxxxx6375 "," redirect_uri ":" http: // localhost: 5000 / oauth / githubcallback "," scope ":" repo " }}}

Terlepas dari ruang lingkup di bawah ini, jika Anda ingin mempelajari lebih lanjut tentang perannya, saya akan membicarakannya nanti.


Langkah ketiga: tulis kode

Masukkan komponen di file Startup.cs:


// Metode ini dipanggil oleh runtime. Gunakan metode ini untuk menambahkan layanan ke container.public void ConfigureServices (IServiceCollection services) {services.AddControllersWithViews (); services.AddSingleton (new GithubOAuth (OAuthConfig.LoadFrom (Configuration, "oauth: github ")));}

Kode lain di dalam file belum diubah, hanya baris ini yang ditambahkan.


Buat kelas OAuthController baru, kodenya adalah sebagai berikut:


menggunakan System.Threading.Tasks; menggunakan Microsoft.AspNetCore.Mvc; menggunakan MrHuo.OAuth.Github; namespace GithubLogin.Controllers {kelas publik OAuthController: Controller {[HttpGet ("oauth / github")] IActionResult Github publik ([FromServices] GithubOAuth githubOAuth) {return Redirect (githubOAuth.GetAuthorizeUrl ());} [HttpGet ("oauth / githubcallback")] public async Task <IActionResult> GithubCallback ([FromServices] GithubOAuth githubOAuth code (authwait return] stringO (kode FromQuery return JubsonA) { .AuthorizeCallback (kode));}}}

Anda membacanya dengan benar, hanya kode ini. Mari kita coba:




Setelah proyek berjalan, masukkan alamat berikut di bilah alamat: otorisasi github:




Setelah mengklik tombol Otorisasi berwarna hijau, tunggu sebentar, dan Anda akan melihat hasil sebagai berikut:




Saya mendapat informasi pengguna dengan lancar (NB: Abaikan beberapa penggemar saya yang malang, saya tidak memaksanya --ToT)




Oke, inilah akhir dari penampilan saya. Anda dapat melihat bahwa proses aksesnya sangat lancar, dan pemegang kartu utamanya mengajukan langkah-langkah ini. Mari kita bicara tentang prinsip dan sejenisnya, katakan saja ... Jika menurut Anda saya bertele-tele, maka Anda tidak perlu membacanya, karena saya akan lebih bertele-tele di bawah ini.


Tentunya selain github, sekarang saya sudah terkoneksi dengan 12 platform. Diantaranya QQ dan Douyin tidak terdaftar di aplikasi dan tidak bisa diuji. Makanya, untuk saat ini belum ada paket nuget. Kekuatan satu orang selalu terbatas. Di sini saya meminta Anda untuk memiliki waktu luang Atau orang besar dengan sumber daya yang memadai, yang memberikan kontribusi untuk proyek kecil ini, adalah orang yang melangkah lebih jauh.




Untuk paket nuget lainnya, kunjungi https://www.nuget.org/profiles/mrhuo atau cari MrHuo.OAuth di manajer paket VS nuget.


Harap abaikan paket sampah lainnya di nuget. Mereka ditulis bertahun-tahun yang lalu dan enggan untuk menghapusnya.


Latar belakang pengembangan

Terus terang, login platform pihak ketiga adalah untuk mengimplementasikan protokol OAuth2. Banyak platform seperti Alipay, Baidu, github, Microsoft, dan bahkan Douyin dan Kuaishou menyediakan antarmuka terbuka. Namun, banyak platform akan menambah atau mengubah beberapa hal berdasarkan protokol standar ini. Misalnya, dalam protokol standar, client_id harus disediakan saat mendapatkan kode otorisasi, dan platform publik WeChat harus mengubahnya menjadi appid. Contoh lain: Saat memperoleh informasi pengguna, hanya parameter access_token yang diperlukan. Platform publik WeChat harus menyediakan openid. Tentu saja, hal ini tidak dapat dihindari, karena sebenarnya bisnis masing-masing platform masih sangat berbeda dan tidak dapat disatukan sepenuhnya. Ini adalah masalah bagi kami pengembang. Sulit untuk mengembangkan login pihak ketiga. Tentu saja, tidak masalah jika Anda mengembangkan satu atau dua. Bagaimana jika ada lebih banyak?


Jika ada manajer produk seperti itu, dia ingin mengakses banyak metode masuk, sehingga pengguna dapat masuk dengan lancar di sini dan menemukan jalan pulang, apa pun platform yang mereka gunakan (PS: manajer produk, jangan dijalankan, perhatikan saya 40 M's pisau besar).




Tidak diragukan lagi, untuk memberi kami tes, bagaimana mencapai standar, dapat dikonfigurasi dan diperluas? Ini adalah pertanyaan yang perlu diselidiki. Sekarang saya akan berbicara tentang beberapa pemikiran saya tentang proyek hati ini. Jangan semprotkan saya jika Anda tidak mengatakannya dengan baik. Saya masih muda (PS: Jangan berpura-pura menjadi pria yang lembut di usia tiga puluhan) , dan wajah ...




Perkembangan standar

Setelah membaca banyak dokumen, kita akan menemukan bahwa selalu ada aturan yang harus diikuti.Secara umum, ada 3 langkah berikut:


GetAuthorizeUrl

Langkah ini menggunakan client_id, redirect_uri dan parameter lain untuk mendapatkan url otorisasi. Setelah melompat ke url ini, login akan diselesaikan di platform pihak ketiga. Setelah login selesai, itu akan dialihkan ke alamat redirect_uri yang disediakan di atas dengan parameter kode..


GetAccessToken

Pada langkah ini, setelah mendapatkan kode di atas, pergi ke platform pihak ketiga untuk mengubah access_token.


GetUserInfo

Langkah ini tidak perlu, tetapi karena kami melakukan login pihak ketiga, setelah login, kami masih perlu mengikat akun pengguna dengan beberapa layanan di platform kami, atau menggunakan informasi yang ada untuk mendaftarkan pengguna. Metode ini sangat penting.


Sejauh ini, menurut saya 3 langkah ini perlu dirumuskan dalam standar, jadi saya menulis antarmuka berikut untuk menstandarkannya:


/// <summary> /// OAuth login API spesifikasi antarmuka /// </summary> antarmuka publik IOAuthLoginApi <TAccessTokenModel, TUserInfoModel> di mana TAccessTokenModel: IAccessTokenModel di mana TUserInfoModel: IUserInfoModel {/// <summary> /// Dapatkan lompatan URL Resmi /// </summary> /// <param name = "state"> </param> /// <returns> </returns> string GetAuthorizeUrl (string state = ""); /// <summary> /// Dapatkan AccessToken secara asinkron /// </summary> /// <param name = "code"> </param> /// <param name = "state"> </param> /// <returns> < / return> Task <TAccessTokenModel> GetAccessTokenAsync (string code, string state = ""); /// <summary> /// Dapatkan detail pengguna secara asinkron /// </summary> /// <param name = "accessTokenModel"> </param> /// <returns> </returns> Task <TUserInfoModel> GetUserInfoAsync (TAccessTokenModel accessTokenModel);}

Anda dapat melihat bahwa saya membuat parameter generik AccessToken dan UserInfo karena keduanya adalah bagian variabel dalam spesifikasi ini. Fungsi parameter status dalam kode adalah untuk mencegah verifikasi anti-pemalsuan serangan CORS. Saya tidak akan menjelaskannya di sini. Dokumen lain memiliki penjelasan tentang parameter ini.




Bagaimana cara memperluas platform baru

Inilah Gitee sebagai demonstrasi:


Langkah pertama: Temukan dokumen OAuth yang sesuai dengan platform, temukan antarmuka informasi pengguna untuk mengembalikan JSON, dan konversikan ke kelas entitas C #. sebagai berikut:

Perluas atribut pengguna sesuai dengan kebutuhan dan standar antarmuka mereka


public class GiteeUserModel: IUserInfoModel {[JsonPropertyName ("name")] public string Name {get; set;} [JsonPropertyName ("avatar_url")] public string Avatar {get; set;} [JsonPropertyName ("message")] public string ErrorMessage {get; set;} [JsonPropertyName ("email"))] public string Email {get; set;} [JsonPropertyName ("blog")] public string Blog {get; set;} //...Properti lainnya mirip dengan di atas}

Pustaka serialisasi Json bawaan .netcore digunakan di sini, dan dikatakan bahwa kinerjanya telah meningkat pesat!


Langkah 2: Tulis antarmuka otorisasi dari platform yang sesuai

/// <summary> /// https://gitee.com/api/v5/oauth_doc#//// </summary> kelas publik GiteeOAuth: OAuthLoginBase <GiteeUserModel> {public GiteeOAuth (OAuthConfig oauthConfig): base (oauthConfig ) {} string penggantian yang dilindungi AuthorizeUrl => "https://gitee.com/oauth/authorize"; string penggantian yang dilindungi AccessTokenUrl => "https://gitee.com/oauth/token"; string penggantian yang dilindungi UserInfoUrl => " https://gitee.com/api/v5/user ";}

Dengan komentar, total sepuluh baris, seperti yang Anda lihat, sangat nyaman. Jika protokol platform mengikuti pengembangan standar OAuth2, beberapa baris saja sudah cukup.


Tentu saja, jika Anda tidak menyesuaikan platform lapangan sesuai aturan, Anda juga dapat memperluasnya, seperti platform publik WeChat.


Ekstensi kelas AccessToken WechatAccessTokenModel.cs


namespace MrHuo.OAuth.Wechat {kelas publik WechatAccessTokenModel: DefaultAccessTokenModel {[JsonPropertyName ("openid")] string publik OpenId {get; set;}}}

Diwariskan dari DefaultAccessTokenModel, bidang baru OpenId ditambahkan, karena untuk mendapatkan informasi pengguna memerlukan OpenId, sehingga dibutuhkan di sini.


Kelas Informasi Pengguna WechatUserInfoModel.cs


using System.Collections.Generic; using System.Text.Json.Serialization; namespace MrHuo.OAuth.Wechat {public class WechatUserInfoModel: IUserInfoModel {[JsonPropertyName ("nickname")] public string Name {get; set;} [JsonPropertyName (" headimgurl ")] public string Avatar {get; set;} [JsonPropertyName (" language ")] public string Language {get; set;} [JsonPropertyName (" openid ")] public string Openid {get; set;} [JsonPropertyName ( "sex")] public int Sex {get; set;} [JsonPropertyName ("provinsi")] string publik Provinsi {get; set;} [JsonPropertyName ("city")] string publik Kota {get; set;} [JsonPropertyName ("country")] public string Country {get; set;} /// <summary> /// Informasi hak istimewa pengguna, json array, seperti pengguna WeChat Woka adalah (chinaunicom) /// </summary> [JsonPropertyName ( "privilege")] public list <string> Privilege {get; set;} [JsonPropertyName ("unionid")] string publik UnionId {get; set;} [JsonPropertyName ("errmsg")] string publik ErrorMessage {get; set; }}}

Di sini, [JsonPropertyName ("xxxx")] di atas bidang informasi pengguna ditulis persis sesuai dengan bidang di dokumen, jika tidak, nilai yang benar tidak dapat diperoleh. Jika Anda tidak membutuhkan terlalu banyak bidang, hapus sendiri.


Kelas inti WechatOAuth.cs


menggunakan System.Collections.Generic; namespace MrHuo.OAuth.Wechat {/// <summary> /// Referensi dokumentasi terkait Wechat OAuth: /// <para> https://developers.weixin.qq.com/doc/offiaccount /OA_Web_Apps/Wechat_webpage_authorization.html </para> /// </summary> kelas publik WechatOAuth: OAuthLoginBase <WechatAccessTokenModel, WechatUserInfoModel> {public WechatOAuth (OAuthConfig oAuthConfig) dilindungi: base (o AuthorizehConfig oAuth) https} override string> Authorizeh //open.weixin.qq.com/connect/oauth2/authorize "; string penggantian yang dilindungi AccessTokenUrl =>" https://api.weixin.qq.com/sns/oauth2/access_token "; string penggantian yang dilindungi UserInfoUrl =>" https://api.weixin.qq.com/sns/userinfo "; protected override Dictionary <string, string> BuildAuthorizeParams (status string) {return new Dictionary <string, string> () {[" response_type "] =" kode ", [" appid "] = oauthConfig.AppId, [" redirect_uri "] = System.Web.HttpUtility.UrlEncode (oauthConfig.RedirectUri), [" scope "] = oauthConfig.Scope, [" state "] = state };} public override string GetAuthorizeUrl (string state = "") {return $ "{base.GetAuthorizeUrl (state)} # wechat_redirect";} dilindungi override Dictionary <string, string> BuildGetAccessTokenParams (Kamus <string, string> authorizeCallbackParams) { kembalikan Kamus baru <string, string> () {["grant_type"] = "authorization_code", ["appid"] = $ "{oauthConfig.AppId}", ["secret"] = $ "{oauthConfig.AppKey}" , ["code"] = $ "{authorizeCallbackParams [" code "]}"};} kamus ganti yang dilindungi <string, string> BuildGetUserInfoParams (WechatAccessTokenModel accessTokenModel) {kembalikan Kamus baru <string, string> () {["access_token" ] = accessTokenModel.AccessToken, ["openid"] = accessTokenModel.OpenId, ["lang"] = "zh_CN",};}}}

Sekilas kontennya begitu banyak, bingung? Jangan bingung, izinkan saya membicarakannya satu per satu:


Proteksi override Dictionary <string, string> BuildAuthorizeParams (status string) {return new Dictionary <string, string> () {["response_type"] = "code", ["appid"] = oauthConfig.AppId, ["redirect_uri"] = System.Web.HttpUtility.UrlEncode (oauthConfig.RedirectUri), ["scope"] = oauthConfig.Scope, ["state"] = state};}

Pembaca yang cermat telah menemukan bahwa paragraf ini adalah untuk membuat daftar parameter di belakang Url Otorisasi, dan mengembalikan Kamus <string, string>, mengira bahwa bidang client_id dari akun resmi WeChat diubah menjadi appid, sehingga perlu ditangani sini.


public override string GetAuthorizeUrl (string state = "") {return $ "{base.GetAuthorizeUrl (state)} # wechat_redirect";}

Paragraf ini diakhiri dengan #wechat_redirect di akhir Url Otorisasi. Meskipun saya tidak tahu artikel WeChat tentang parameter ini (PS: teman yang tahu, katakanlah ~~), biarkan dia menulisnya di dokumennya.


protected override Dictionary <string, string> BuildGetAccessTokenParams (Dictionary <string, string> authorizeCallbackParams) {kembalikan Kamus baru <string, string> () {["grant_type"] = "authorization_code", ["appid"] = $ "{oauthConfig .AppId} ", [" secret "] = $" {oauthConfig.AppKey} ", [" code "] = $" {authorizeCallbackParams ["code"]} "};}

Dengan cara yang sama, paragraf ini untuk membangun parameter antarmuka GetAccessToken.


Proteksi override Dictionary <string, string> BuildGetUserInfoParams (WechatAccessTokenModel accessTokenModel) {return Kamus baru <string, string> () {["access_token"] = accessTokenModel.AccessToken, ["openid"] = accessTokenModel.OpenId, ["lang"] = "zh_CN",};}

Dengan cara yang sama, paragraf ini adalah untuk membuat parameter antarmuka GetUserInfo.


Seperti yang Anda lihat, framework ini didasarkan pada prinsip kebebasan dan keterbukaan, apa pun yang dapat disesuaikan dapat disesuaikan. Juga, titik awal asli saya tidak hanya untuk login OAuth. Saya ingin mengintegrasikan semua API yang disediakan di platformnya karena terlalu mudah untuk dikembangkan, tetapi saya memiliki waktu dan energi yang terbatas. Selain itu, orang-orang semakin tua dan kewalahan. Oleh usia 30, otak saya tidak terlalu cemerlang, jadi kesempatan disediakan untuk orang muda.


Bergabunglah dengan kontribusi

Saya berharap lebih banyak teman bergabung dengan proyek ini, baik dengan menyumbangkan kode, dengan menyumbangkan sumber daya appid untuk pengujian, atau dengan memberikan saran. Jika Anda juga tertarik, silakan hubungi saya.


Jika Anda merasa berguna untuk membantu Anda, berkontribusi pada bintang taman kanak-kanak ⭐, klik perhatiannya, dan lambaikan tangan ~~ (PS: manual nakal)


Dokumen terkait:

OAuth2: https://oauth.net/2/

Github: https://github.com/mrhuo/MrHuo.OAuth

Website resmi: https://oauthlogin.net/

Comments

Popular posts from this blog

Prediksi tren mandiri 2021: model butik menempati arus utama, ketiga jenis penjual ini lebih kompetitif

Apakah alien hidup di alam semesta? Atau hidup di bumi?