本篇文章主要介紹了nodejs實作OAuth2.0授權服務認證,現在分享給大家,也為大家做個參考。
OAuth是一種開發授權的網路標準,全拼為open authorization,即開放式授權,最新的協定版本是2.0。
舉個栗子:
有一個"雲沖印"的網站,可以將使用者儲存在Google的照片,沖印出來。使用者為了使用該服務,必須讓"雲端沖印"讀取自己儲存在Google上的照片。
傳統方法是,使用者將自己的Google使用者名稱和密碼,告訴"雲端沖印",後者就可以讀取使用者的照片了。這樣的做法有以下幾個嚴重的缺點。
"雲端沖印"為了後續的服務,會儲存使用者的密碼,這樣就很不安全。
Google不得不部署密碼登錄,而我們知道,單純的密碼登入並不安全。
"雲端沖印"擁有了取得使用者儲存在Google所有資料的權力,使用者沒法限制"雲端沖印"授權的範圍和有效期限。
使用者只有修改密碼,才能收回賦予"雲沖印"的權力。但是這樣做,會使得其他所有獲得使用者授權的第三方應用程式全部失效。
只要有一個第三方應用程式被破解,就會導致使用者密碼洩漏,以及所有被密碼保護的資料外洩。
所以OAuth就誕生了!
Third-party application:第三方應用程序,本文中又稱為"客戶端"(client),即上一節範例中的"雲沖印"。
HTTP service:HTTP服務提供者,本文簡稱"服務提供者",即上一節範例中的Google。
Resource Owner:資源擁有者,本文又稱為"使用者"(user)。
User Agent:使用者代理,本文就是指瀏覽器。
Authorization server:認證伺服器,也就是服務提供者專門用來處理認證的伺服器。
Resource server:資源伺服器,也就是服務供應商存放使用者產生的資源的伺服器。它與認證伺服器,可以是同一台伺服器,也可以是不同的伺服器。
登入層提供令牌(token)的生成,其中token包含:有效期、權限範圍。客戶端拿到token去存取受限資源。
access_token:要求資源時需要攜帶的token,即存取token。
refresh_token:刷新token,如果access_token過期,可以使用該token取得一份新的access_token和新的refresh_token。一般refresh_token時效性較長,例如一年,而access_token時效性較短,例如幾分鐘。
權限範圍:即指定用戶端可以取得的資源權限範圍。
OAuth授權模式
OAuth有四個授權模式,分別為:
授權碼模式(authorization code)
簡化模式(implicit)
密碼模式(resource owner password credentials)
客戶端模式(client credentials)
#1、授權碼模式
授權碼模式是最嚴密的授權模式,整體流程為:瀏覽器攜帶必要資訊至授權頁面,正常登入成功後,返回一個code(授權碼),客戶端拿到code後在後台取得拿code換取token。
2、密碼模式
密碼模式,簡單地理解即為使用用戶名稱密碼等參數取得access_token,它的步驟如下:
使用者向客戶端提供使用者名稱和密碼。
客戶端將使用者名稱和密碼傳送給認證伺服器,向後者請求令牌。
認證伺服器確認無誤後,向客戶端提供存取令牌。
3、refresh_token的應用程式
refresh_token被用來取得新的access_token和refresh_token,使用方式簡單如下:
refresh_token無效:
使用nodejs實作OAuth授權服務
技術堆疊:
nodejs eggjs
#eggjs-oAuth-server外掛程式
# 具體可以參考:
https://github.com/Azard/egg-oauth2-server
https://cnodejs.org/topic/592b2aedba8670562a40f60b
#1、code grant模式測試及單一登入實作
這裡我們建構兩個站點,一個是7001埠(授權服務),一個是7002埠(客戶端),授權模式為code grant。
首先是用戶端登入頁:
點擊按鈕後直接登入:
可以發現,瀏覽器重定向到授權服務位址,並攜帶了response_type、client_id、redirect_uri
三個參數,登入成功後,瀏覽器會重定向到redirect_uri
指定的位址,即這裡的*http://127.0.0.1:7002/auth/redirect*:如下為授權服務的登入頁寫法
<form action="/oauth2/authorize?{{query}}" id="form1" name="f" method="post"> <p class="input_outer"> <span class="u_user"></span> <input name="username" class="text" style="color: #FFFFFF !important" type="text" placeholder="请输入账户"> </p> <p class="input_outer"> <span class="us_uer"></span> <input name="password" class="text" style="color: #FFFFFF !important; position:absolute; z-index:100;"value="" type="password" placeholder="请输入密码"> </p> <p class="mb2"><a class="act-but submit" href="javascript:;" rel="external nofollow" onclick="document.getElementById('form1').submit()" style="color: #FFFFFF">登录</a></p> </form>這裡的${query} 即為客戶端登入重定向攜帶的完整query,然後是
/oauth2/authorize路由的寫法:
app.all('/oauth2/authorize', app.oAuth2Server.authorize());// 获取授权码這裡呼叫
app.oAuth2Server.authorize()
時,外掛程式會自動執行重定向操作,先是重定向到客戶端指定位址,客戶端拿到code和state後,再去授權層取得token:async redirect(){ // 服务端重定向过来的 console.log(this.ctx.query) const result = await this.ctx.curl('http://127.0.0.1:7001/users/token', { dataType: 'json', // contentType: 'application/x-www-form-urlencoded', // 默认格式 method: 'POST', timeout: 3000, data: { grant_type: 'authorization_code', code: this.ctx.query.code, state: this.ctx.query.state, client_id: client_id, client_secret: client_secret, redirect_uri: redirect_uri, } }); this.ctx.body = result.data; }取得到token後正常回傳:
2、password grant模式測試
首先使用username、password取得access_token:
#使用者名稱或密碼錯誤時傳回:
#使用token取得授權資源正常回傳:
以上是在nodejs中如何實作OAuth2.0授權服務認證的詳細內容。更多資訊請關注PHP中文網其他相關文章!