2017年1月15日 星期日

Microsoft Graph API (2) - 使用OAuth進行身分驗證,並取得用戶資訊

我們前面曾經和大家聊過,如果要幾句話說清楚Microsoft Graph API是啥,其實並不很容易,但透過先前的介紹你大概可以知道,Microsoft Graph API身為MS Office 365所有資源存取的API連線入口,負擔著讓開發人員得以輕鬆存取雲端資料(資源)的重要角色,只要你想存取Office 365、OneDrive、OneNote…等各種資源,基本上你就必須與Graph API打交道:

不管用戶採用的是個人帳號(Microsoft Account)或企業帳號(Orgnization Account),MS Graph API讓開發人員可以用單一Endpoint允許各種不同帳號的身分驗證,當然也會依照權限吐出不同的資源。

這一篇我們接著來看,如何透過OAuth連結MS Graph API,並且取得token抓取用戶資料。
(如果讀者對OAuth還不甚了解,請先參考這裡)

建立Microsoft應用程式

首先,若您是開發人員,要使用MS Graph API(或者是要與O365/Onedrive等系統做SSO),你必須先在微軟的站台上建立一個Application,建立的位置在: https://apps.dev.microsoft.com/ ,進入之後會看到底下畫面:

請用您的Microsoft Account登入,您就可以建立一個自己的應用程式:

點選後會出現底下畫面,依照步驟,輸入名稱,按下建立鈕:

建立完應用程式之後,請接著點選『產生新密碼』:

記得保留上面彈出視窗中顯示的密碼,待會我們會使用到(它只會顯示一次,請務必自行保留)。

接著,請在平台這邊選擇新增平台,然後選Web,這是因為我們範例中是透過Web App整合方式來進行Demo,如果你的情境是要在行動裝置上存取Office365(or Onedrive/onenote…etc.)中的資源,當然就選擇行動應用程式:

接著該頁面會要求你輸入重新導向URI,這部分如果不理解其意義以及為何需要,請參考我們以前分享過的OAuth介紹文,底下的URL就是你取得Auth Code的導回網址,由於我們只是要在Local用IIS Express測試,因此我們網址輸入Localhost:

至於port 13555怎麼來的,它是我們在VS2015中建立了一個Web Application Project之後自動產生的,如果你想測試但懶得寫程式,可以拿我在GitHub上面的範例來修改:
https://github.com/isdaviddong/MsGraphApiExample20170115

接著,請至少為您建立的應用程式新增user.read這個權限,如果你想玩其他的權限,可點選下圖的『加入』鈕:

設定完成之後,請按下儲存鈕(請務必保持Live SDK勾選):

撰寫OAuth/SSO登入頁面

完成了上面所有的設定之後,您的應用程式就建立好了,請取得應用程式中的『應用程式識別碼(Client_id)』與『密碼(Client_Secret)』,應該長得像是底下這樣:
Client_id : 98d720db-xxxx-xxxx-xxxx-7430359c1c10  (這是假的)
Client_Secret : teoXXXeJp8bxxxxSO2HjhNG (這當然也是假的)
有了上面的資訊就夠囉。

接著請撰寫底下的頁面(如果你想測試但懶得寫程式,可以拿我在GitHub上面的範例來修改:https://github.com/isdaviddong/MsGraphApiExample20170115):

然後在VS2015的IIS Express中運行此頁面,你會發現點選上圖中的Button之後,會被導引到AAD2.0的登入畫面:

您可以用Microsoft Account或Orgnization Account登入都行,因為Graph API都支援。(但用哪一種帳號登入後面的畫面將會有所不同,我們在本文中的展示是以Microsoft Account登入)

用戶登入之後,系統會跟他要求資訊存取權限:

你會發現上圖(1)的地方就是您建立您的應用程式時,所上傳的圖示,而(2)的地方是您的應用程式名稱,(3)是您跟用戶要的權限 (4)是…就只是一個用戶非點不可的按鈕。

當用戶成功登入之後,網頁會被導回你原先的頁面,但這時,請注意網址列QueryString已經出現了Auth Code:

請取得該Code,我們要用此Code換Token。

後面的動作我用postman示範,取得auth code之後,請對https://login.microsoftonline.com/common/oauth2/v2.0/token這個位置做POST呼叫,並傳入下列參數:

上圖中的(1)是你原本在應用程式以及要求Auth Code的登入URL中所設定的redirect_url(必須都相同),(2)與(3)是一開始我們請你保留的client_id和client_secret,而(4)則是剛才從QueryString取得的Auth Code,成功呼叫之後,你會發現上圖下方API回給我們了Access_token,將其保留起來,該Token就是我們依照權限取得用戶資訊的令牌了。

透過token抓取用戶資訊

拿到token之後你就無敵了,基本上你可以用該token來取得所有用戶授權你抓取的資訊(如果用戶授權你更新,你當然也能修改用戶資訊)。

底下我們依舊用postman來示範,例如,倘若你要取得用戶身分,可以對https://graph.microsoft.com/beta/me這個網址做GET,並傳入底下資訊:
上圖中的Authorization參數當然傳遞我們剛才取得的token,而結果就是上圖下方取得的JSON資訊,你會看到其中有用戶的個人身分資訊。

就這樣,如我你還想取得其他資訊,可以透過哪些API呢? 很多,例如底下是常見的:

更多詳細的資訊可參考 http://graph.microsoft.io/en-us/docs

有沒有發現,當你熟悉了OAuth之後,透過API要取得用戶的資訊其實非常容易。
--------------------------------------------
如果需要即時取得更多相關訊息,可按這裡加入FB專頁。若這篇文章對您有所幫助,請幫我們分享出去,謝謝您的支持。

2017年1月13日 星期五

asp.net Web開發框架 (7) - 使用Vue.js進行表單雙向繫結

先前我們分別討論過了使用Vue.js進行表格資料渲染以及渲染時動態產生的功能性按鈕之後,接著,我們來看Vue.js在表單上的資料繫結。

範例依舊是我們先前使用的那個:
source code : https://github.com/isdaviddong/AspNetWithVueBinding
測試網址: http://ex20170110-aspnetwithvuebinding.azurewebsites.net/ 
(如果該網站被我不小心殺掉,請FB訊息提醒我,網站裡面的資料由於是共用的,可能會被玩壞或出現詭異的內容,一概與本人無關XD )

看過了先前的介紹之後,你大概已經知道,動態產生的『編輯』鈕:

該按鈕會在用戶點選時,將畫面導入到AddNewOrUpdate.html這個頁面,進行編輯的動作,而首頁上的新增鈕,其實也是將網頁導入到AddNewOrUpdate.html這個頁面。唯一的差異在,如果是按下編輯鈕,該筆紀錄的guid會被帶入:

這個動作怎麼實現的,答案在我們先前進行動態Button渲染時候的Vue instance中的edit method:

這使得如果用戶按下的是新增鈕,AddNewOrUpdate.html這個頁面將不會收到QueryString,若用戶按下的是編輯鈕,則是用戶欲編輯的record的guid。

因此,我們就不難理解AddNewOrUpdate.html這個頁面一開始進入後的javaScript code,就是判斷是否有Guid:

我們把guid保留在12行的變數中,30行之後的document ready,則是判斷是否有guid,如果有,則在36行呼叫LoadData,把該筆資料載入。而不管有沒有資料,31行的SetBinding都會把UI上的HTML表單與記憶中的vd_StudentRec做繫結:

所以你不難猜到,LoadData這個function,在從遠端載入完資料之後,會放到哪一個地方? (別往下看,先想一下…)

答案當然是:

記憶體中的vd_StudentRec,沒錯。其實,上面這段程式碼是為了說明,否則在實務上你把回傳的資料result.Data,直接放入Vue.js的instance就好(vm_student.rec=result.Data),因為vm_student.rec根本就是vd_StudentRec的代理。

好的,資料塞入vm_student.rec,會觸發Binding,Vue.js的Binding Engine會去找HTML UI上的Form_StudentRec:

然後它發現你寫的v-model指令,這表示該欄位要進行雙向繫結(two-way binding),因此,Vue.js engine就會把你繫結的物件vd_StudentRec中的屬性值帶入,這就是畫面上的表單資料會自動呈現的原因。

同樣的,由於是Vue.js是設定雙向繫結,因此進入AddNewOrUpdate.html這個頁面之後,不管是有沒有透過QueryString的參數載入一筆預設的資料,任何表格上使用者的異動都會被反應到記憶體中的vd_StudentRec物件中,因此,當用戶按下畫面上的『新增/更新』鈕:

頁面上的JavaScript程式碼,做的就是把記憶體中的vd_StudentRec物件中的值,透過呼叫後端的AddNewOrUpdate方法,寫回後端資料庫中,程式碼如下:

後端的AddNewOrUpdate方法也很簡單,就是取得傳入的物件,然後判斷一下是否有guid(1),如果沒有,應該是新增(2),如果有,就從資料庫中找出來更新(3):

就這樣而已,相當單純。

以上提到的完整程式碼都在 https://github.com/isdaviddong/AspNetWithVueBinding 請自行參考。

--------------------------------------------
如果需要即時取得更多相關訊息,可按這裡加入FB專頁。若這篇文章對您有所幫助,請幫我們分享出去,謝謝您的支持。

2017年1月10日 星期二

asp.net Web開發框架 (6) - 在Vue.js動態表格渲染中加上功能按鈕

接續著上一篇,我們這次拿這個WebAPI + Vue.js 的CRUD範例繼續討論。讀者可以點選這邊,看看這個範例的實際執行狀況。(如果該網站被我不小心殺掉,請FB訊息提醒我,網站裡面的資料由於是共用的,可能會被玩壞或出現詭異的內容,一概與本人無關XD )

這個網站的主畫面如下:

上一篇我們大致上說過,這些資料是透過伺服器端以JSON格式傳到前端,並且透過Vue.js的template rendering機制動態顯示出來的。

但我們沒有談到,上圖中每一個row最左邊的編輯/刪除鈕,是怎麼實現的,我們這一篇就來介紹這個部分。

在HTML Tempalte中加上功能按鈕

先前我們看過的HTML樣板,要加上Button很容易,但Button要有對應的功能,則需要透過v-on:click 指令:

你會發現,上面的第4,5兩行,多了兩個Button,就是編輯和刪除鈕,分別是呼叫到edit和remove這兩個javascript function,並且傳入item作為參數,還記得嗎?這個item就是第2行v-for裡面的item in items的那個item,也就是伺服器端傳來的資料集合中的一筆資料。

因此,當用戶點選這兩個Button,實際上會執行到的,就是Vue.js的vm裡面所定義的methods(位於12-22行) :

 

這個在Vue.js稱之為方法事件處理器。留意上述程式碼的第12-22行,其中的edit、remove,就是按下Vue.js動態渲染出的Button時,會觸發的JavaScript Functions(Methods),由於帶入的參數是item,也就是按下哪一筆資料的Button,就把該筆資料作為參數帶入。因此function裡面的程式碼就不難理解了。

remove method的14-16行會出現confirm(…)視窗,如果用戶確認刪除,則調用Remove(item)這個我們自己寫的JavaScript Function。而19行則是edit method,功能是redirect網頁到AddNewOrUpdate.html,並帶入資料record的Guid作為QueryString參數(由於AddNewOrUpdate.html這個網頁因為同時包含新增與修改兩種功能,比較複雜我們改天討論)。

我們先看14-16行中所呼叫到的Remove(item)這個JavaScript,也就是上述程式碼的26-37行,如果熟悉我們這一系列文章的讀者肯定知道,其中的ExecuteAPI是我們框架提供的JavaScript function,他會呼叫到伺服器端的Remove()這個BO中的C# Method,並傳入guid當作參數。

後端刪除資料的方法

因此我們看後端的C# Code,果然,有一個叫做Remove(Guid guid)的方法:

該方法中的程式碼就是找到guid編號符合的資料,然後刪了它,接著呼叫GetData()這個我們先前介紹過的Method把所有資料以JSON格式回傳給前端,如此這般,達成了資料刪除的功能。

如果你仔細看程式碼,可能會發現,其實前端並沒有拿remove方法回傳過來的JSON,而是自己又呼叫了一次GetData(),為何要這樣寫呢? 這樣不是多呼叫了一次,讓效能變差嗎? 答案是…沒什麼特別原因,就是寫的時候不小心忘了,寫完後又懶得改而已…

所以,整段的重點在於,透過Vue.js做HTML樣板(Tempalte)動態渲染(Rendering)的時候,如果有某些tag需要觸發事件,可以在HTML Template當中直接透過 v-on,以事件處理器的方式,呼叫預先定義在Vue instance當中的Methods,達成所需的效果,就像是我們在上面這個例子中的Remove與edit一樣。

以上提到的完整程式碼都在 https://github.com/isdaviddong/AspNetWithVueBinding 請自行參考。

改天有空我們再繼續討論新增與修改的功能。

--------------------------------------------
如果需要即時取得更多相關訊息,可按這裡加入FB專頁。若這篇文章對您有所幫助,請幫我們分享出去,謝謝您的支持。

2017年1月5日 星期四

asp.net Web開發框架 (5) - 使用Vue.js進行前端資料繫結顯示(WebAPI版本)

前面寫過了在asp.net WebForms環境下使用Vue.js做DataBinding/UI Template Rendering,這一篇我們把焦點轉回WebAPI的版本。

如果使用前面介紹過的寫法,以WebAPI搭配Vue.js進行SPA Web應用程式開發,那前端的頁面可以是很單純的pure HTML,例如:

先前介紹過的一樣,UI上進行Binding的部分只有60-90這一個區段,透過Vue.js的繫結語法{{item.xxxx}}把每一個屬性的值填入UI,而促使這個Binding生效的js程式碼位於14-21行,也就是SetBinding()這個javascript function。這個SetBinding()建立了vm_StudentInfo這個Vue instance,把HTML UI上的tableBody與vd_StudentInfo這個記憶體物件做了繫結。

因此,每當vm_StudentInfo的items屬性被更新時,Vue就會拿vd_StudentInfo中的數據來更新tableBody區塊中的UI。

而底下這段程式碼(24-31行)則是binding_StudentInfo的items屬性被更新的時機:

也就是畫面上的『Get Data』Button被按下去的時候。會透過ExecuteAPI呼叫伺服器端的WebAPI,因此底下的程式碼被執行(還記得這一大段WebAPI程式碼在幹嘛? 我們曾經在先前詳細的介紹過):

是面這段WebAPI身為服務層,任務就是動態載入並執行相對應的BO,因此進而運行到BO.Health.GetData這個GetData Method:

執行後的結果List<StudentInfo>會透過JSON回傳到前端,被透過Vue 的DataBinding(Template Rendering)機制顯示於螢幕上:

同樣的,按下上圖中的『清空』鈕之後畫面會被清空的原因也很好理解,我們只是把繫結物件的items屬性清空:

因為vm_StudentInfo.items 被設為 undefined(或其他空值),則頁面上顯示的資料就被清空了,就是這麼簡單。

其他的部分我們在上一篇介紹過囉…(先前針對程式碼相關更完整的解釋請參考這裡)

source code : https://github.com/isdaviddong/AspNetWebFormsSpaVueBinding

更完整的WebAPI版本CRUD Source Code:
  https://github.com/isdaviddong/AspNetWithVueBinding

下一篇我們會接著介紹,如何在渲染HTML表格的時候,加上功能按鈕…
--------------------------------------------
如果需要即時取得更多相關訊息,可按這裡加入FB專頁。若這篇文章對您有所幫助,請幫我們分享出去,謝謝您的支持。

2017年1月2日 星期一

asp.net Web開發框架 (4) - 使用Vue.js進行前端資料繫結顯示(Template Rendering)

弱水三千,為何只取Vue.js?

一直以來,我覺得大部分的開發技術其實也是一種工具,也有生命週期。既然是一種工具,那開發技術當然不能只是拿來學習,而應該是拿來使用的。最近幾年,隨著開發技術的生命週期越來越短,不免讓人開始猶豫該如何選擇。如果你慢慢發現,學習某一門技術的時間並沒有遠低於使用它的時間,那就得回頭重新評估這個工具了…

但,千萬別誤會,我不是叫大家不要花時間去進修,或是減少學習的時間。這年頭,我們比過去以前任何一個時代都需要時時刻刻學習。但,正因為我們的時間越來越珍貴,越來越難以過去的大量快速學習來面對技術的變遷,因為現在不管學得再快,也無法趕上變化的腳步…

莫名其妙講了一堆,好像跟這個主題無關?

非也,我想說的是,最近幾年我在專案中選擇的工具(開發技術)時,都盡可能以不用花太多學習時間的為主。因為工具(技術或框架)最終的目的是幫你節省時間用的,倘若學習成本太高,可能會本末倒置。而這個理由,也恰巧是我們選擇Vue.js作為前端開發框架的原因。

當過去幾年我們在.net環境嘗試建構一個適當的開發架構時,三層式的SPA對我們來說是個能同時滿足行動裝置、Web、以及桌面應用的理想選擇,而要採用何者搭配SPA作為Web前端開發套件呢? 最終,我們選擇了Vue.js。

理由?

  1. 它的程式碼很簡潔,非常輕量級,執行速度也算快,一點都不讓人覺得累贅。
  2. 它很好學,還有中文的文件(唯一的遺憾是簡體),對於已經有前後端程式碼分離、SPA基本概念的人,用起來跟喝水差不多。
  3. 它在資料繫結這個部份的做法非常直覺,MVVM概念的實現很接近以前XAML的作法,同時,它採用的標記語法很簡單,也極不容易破壞HTML版面,和設計師(designer)很好合作。

以上是最主要的這幾點。

Demo的前置準備

我們前面說過Vue.js學起來很簡單,因此我們也不用談什麼初階進階的東西。待會的Demo就直接從伺服器端把一組資料傳到前端,然後透過Vue.js做一個Binding(Template Rendering),以表格的方式把從伺服器端傳來的JSON資料呈現出來。
(若需要完整的CRUD請參考本文最後)

如果你想跟我一起 hands-on 一下,請依照底下的操作步驟做好前置準備,別忘了,我們用的是SPA架構,把以前你熟悉的asp.net WebForms或asp.net MVC都先給擱在一邊吧。

補充: 底下的範例是透過WebForms PageMethod來寫SPA,如果你想看WebAPI的SPA版本,請參考Source code,UI的部分請看index.html,同時原本PageMethod相對應的改成了透過WebAPI呼叫BO,請參考ControllerHealth.cs,而程式碼的說明則建議您先看完這篇之後,再接著看下一篇(WebAPI版)。

  1. 請先建立一個最基本的asp.net 應用程式(請用Empty範本,並勾選WebAPI與WebForms),然後只需直接引入一個Nuget套件isRock.Framework.Web.AllPackages,它會幫你引入其他所有需要的Nuget套件:
  2. 接著,請在頁面上建立一個default.aspx (如果你偏好WebAPI版本的SPA,可參考這邊自行傳換成建立WebApi,或待會看下一篇):
  3. 準備工作先到這邊,接著我們來看如何進行Vue資料繫結。
基本概念

開工前我們扼要說一下基本概念,我們接下來要透過Vue.js做一個最基本的資料繫結,整個動作發生於前端,也就是瀏覽器上(這和Silverlight類似),但和過去asp.net WebForms發生在後端的資料繫結有所不同。

所以你必須先知道一件事情,這裡所謂的資料繫結,指的是瀏覽器內的HTML與Object的繫結。也就是,將『從伺服器端透過AJAX呼叫,被以JSON格式傳遞到瀏覽器之後的JavaScript Object』,與『HTML UI』Template之間的資料繫結。

而非像是過去的asp.net webforms或MVC一樣,在伺服器端進行的資料庫與UI Rendering之間的繫結。

大部分的SPA架構,前端顯示的資料都是從伺服器端以JSON的方式傳到前端,所以我們這裡的資料繫結大多談的都是資料被以JSON格式傳到前端瀏覽器上『之後』的資料繫結。

因此,你必須有幾個概念:

  1. UI上的資料不會『直接』與後端資料庫互動,而是在前端瀏覽器的記憶體內與HTML UI互動。
  2. 資料在繫結前,得先從伺服器端(以JSON格式)傳過來。
  3. 倘若是表單繫結,UI上的資料被用戶修改而有所異動,也只是反應回前端瀏覽器內(記憶體中)的Object,並非直接回寫資料庫。

暫時先知道這些就可以了。

要Demo什麼?

我們先來看,如何從伺服器端取得JSON資料,然後透過Vue.js的template動態Render到HTML上的範例(後面會再介紹表單中的資料雙向繫結)。好的,我們待會要做的事情是這樣,畫面上有一個類似底下這樣的UI:

當按下左上角Get Data按鈕的時候,會從伺服器端撈一堆資料,以JSON的格式傳到前端瀏覽器上,透過Vue.js進行DataBinding,呈現出底下的結果:

如果用戶按下上圖中的清空鈕,則表格資料會清空,就這樣。

如何使用Vue.js的template syntax做HTML動態rendering

好,知道要做什麼之後,我們實際來嘗試一下,請在剛才建立好的aspx頁面的CodeBehind程式碼中,建立底下這個Method :

上面這段後端C#程式碼的主要目的,是建立可以往前端傳送資料、可以被前端JavaScript呼叫的PageMethod,角色如同WebAPI或WebServices一般,但.aspx開發人員很幸運,用上面這樣的寫法就行了。

細看程式碼其實很簡單,28-33行就是準備假資料,如果是正式環境,我會從資料庫抓資料,但因為這只是一個範例,我們不要弄得太複雜。注意我們可以直接在同一個頁面上定義ViewData Class,當然也可以獨立做成一個專案或寫在同一個專案的BO(Business Logic Object)資料夾底下,但對於WebForms開發人員我們很包容,暫時先寫在同一個頁面上就好。

35行的迴圈是計算BMI值,最後在46行回傳給前端JavaScript,就這樣。別問我為何那麼簡單,因為 1.它本來就很簡單 2.上面範例用了我們開發的框架,大部分前端AJAX程式碼以及後端資料回傳的類別都包裝過了。

寫好後端C#,待會接著我們來看前端。

後端的PageMethod負責提供資料,留意上面程式碼25行該PageMethod的宣告以及回傳型別,是public static PageMethodDefaultResult<List<StudentInfo>> GetData() {…},由於框架提供的功能,你可以在前端透過底下這樣的JavaScript直接呼叫後端的GetData()這個PageMethod,作法像是底下這樣:
          CallPageMethod('GetData', null,
              //when success
              function (result) {
                 vm_StudentInfo.items = result.Data;;
              }
           );
透過呼叫CallPageMethod這個function,即可執行伺服器端這個名為GetData的PageMethod(由於該Method不需要任何參數,因此上面第二個參數我們給null),並且在成功呼叫之後,透過callback function取得回傳值result,這個result就是剛才PageMethod的回傳物件PageMethodDefaultResult<List<StudentInfo>>,而result.Data則是PageMethod回傳物件中的List<StudentInfo>,也就是實際上我們在前端需要的ViewModel資料,也就是五筆學生的身高體重與BMI值。

那…這個…

vm_StudentInfo.items = result.Data;

這行程式碼什麼意思呢?別急,我們來看前端頁面上完整的程式碼:

請注意UI的部分只有50行之後,UI進行Template Rendering的部分只有64-94行中間的表格部分,而8-11行則是引用我們會用到的js與css。整段程式碼看過之後,我們來看關鍵的幾個部分。

  1. 首先,該頁面一被載入完畢,41行的Document Ready會先被執行,請留意43行的SetBinding設定。後面45,46只是Hook Button的Click事件而已。
  2. 43行呼叫的SetBinding做了什麼呢? 我們看16-23行。整段內容非常簡單,就是透過Vue做一個資料繫結,繫結什麼? 誰跟誰繫結? 就是頁面上的HTML Template與瀏覽器記憶體中的物件vd_StudentInfo。其中20行的el與21行的data,告訴Vue.js的Rendering/Binding engine,當指向vd_StudentInfo這個記憶體物件的items有所異動時,要自動更新(Rendering)頁面上TableBody這一塊的內容。

     
  3. 我們看TableBody,也就是第64行到94行這一塊div :
     
  4. 由於上面的TableBody區塊,是透過{{…}}這樣的語法所設置了的HTML樣板(Template),因此,每當vm_StudentInfo中,指向vd_StudentInfo的這個data(也就是items)有所異動時,el區塊(也就是TableBody)就會被更新。你可能會疑惑兩件事情,(1) items什麼時候會被異動? 以及 (2) el區塊會被怎麼更新?
  5. 首先,請看45行的Button,他被按下時會觸發26行的GetData,透過CallPageMethod呼叫是伺服器端的GetData方法回傳學生資料JSON到前端,透過result.Data傳回,然後我們丟給binding_StudentInfo.items,對,就是這個動作,更新了items,這解答了上面的(1)這個問題。
  6. el區塊會被怎麼更新呢? 因為我們透過了Vue.js設定的Template語法(也就是那些{{…}}),因此,Vue.js Render Engine發現了items有所異動,就會去拿vd_StudentInfo中的值,更新指定的el區塊(tableBody),也就是64-94行的HTML樣板(Template)。
  7. 更新時,會把vd_StudentInfo帶入items,然後請特別注意76行的<tr v-for="item in items">,這一段Vue的v-for語法,意思是接下來的tr區塊(76-92行),會被重複顯示(Render),重複的次數看items這個array的個數決定…別忘了,items就是vd_StudentInfo,而vd_StudentInfo是從伺服器端傳來的List<StudentInfo>…
  8. 由於伺服器端傳來的資料有五筆,因此這個v-for跑了五次,每一次帶入一個StudentInfo item(留意78,81,84…這幾行的繫結語法{{item.屬性名稱}}),資料被帶入表格,呈現出底下的結果:

沒了,就這樣。

這個Template Rendering與過去XAML當中的Binding Engine作法幾乎完全相同。也就是,透過設定Template語法,上面js程式碼中的new Vue(…),把UI Element與記憶體中的Data Object做一個關聯(繫結),一旦繫結綁定了之後,一端有任何變化,另一端也會跟著變化(在表單中使用的話,可透過v-model設為雙向繫結,容後介紹),而搭配上{{…}}這樣的Template顯示語法,在HTML中可以輕易的帶入要呈現的集合資料或變數。

不僅僅語法非常簡潔,HTML Tag的破壞也極少,這是我喜歡Vue.js的原因,他讓SPA可以輕易實現前端的Template Rendering或Data Binding,並且讓設計師(Designer)與程式設計師(Developer)可以開心的合作。

所以…

目前Vue.js幾乎是我們現在開發SPA時,在前端的首選甚至是唯一選擇。上面這整段程式碼是非常常見的應用,只要稍微熟悉Template Rendering或Data Binding概念,可以很快的pick up整個Vue.js的語法與使用,建議沒有使用過的開發人員可以試試看…

後面,我會抽空繼續介紹更進一步的Binding方式,例如在表格中加上Button按鈕之類的…

source code : https://github.com/isdaviddong/AspNetWebFormsSpaVueBinding

Again: 上面是透過PageMethod來寫,如果你想看WebAPI的版本,請參考上面的程式碼,UI的部分請看index.html,PageMethod則改成了透過WebAPI呼叫BO,請參考ControllerHealth.cs ,並接著看下一篇

更完整的WebAPI版本CRUD Source Code:
  https://github.com/isdaviddong/AspNetWithVueBinding
--------------------------------------------
如果需要即時取得更多相關訊息,可按這裡加入FB專頁。若這篇文章對您有所幫助,請幫我們分享出去,謝謝您的支持。

2017年1月1日 星期日

一次搞懂OAuth與SSO在幹什麼?

最近的Line NotifyLine Login,以及前一陣子的Microsoft Graph API,全都使用到了OAuth作為用戶身分驗證以及資源存取的基礎。但很多讀者會卡在OAuth的運作流程上,根本的原因是不理解OAuth到底是幹嘛的?其存在的目的為何?以及如何應用?

因此,我想花一個篇幅,盡可能短的介紹一下OAuth與SSO,但,與坊間文章不同的是,我希望從應用情境的角度(而非技術)切入談這件事情,冀望能夠讓開發人員對OAuth有個最基本的認識。

OAuth的背景

我們回頭看Line LoginLine Notify中的例子,OAuth在這邊最簡單的應用情境,就是身分驗證。典型的情境中有幾個角色,分別是:

  1. 網站或App的開發單位 : 也就是各位開發人員
  2. OAuth服務的提供者(Provider) : 也就是Line(或Google、Microsoft…etc.)
  3. 終端用戶(End-User) : 網站使用者、Line使用者、消費者、客戶…etc.

上面這三者的關係是什麼?

當我們建立一個網站(例如Pc Home購物)、或App(例如一個手機遊戲),都非常有可能需要建立一組會員機制,這些機制包含:

  1. 登入(包含身分驗證,帳號、密碼保存…等)
  2. 個資管理(用戶名稱、地址、電話、暱稱、手機…等)

以往,幾乎都是每一個網站自己做一套,但這樣有很多麻煩事,首先用戶要記得很多組帳號密碼,而每一個網站都自己搞一套會員機制,網站開發人員自己也很辛苦,加上最近這幾年大家都很重視個資,網站儲存(保管)了很多帳號密碼與個人資料,總是會有被駭的風險。因此,這十年來,很多大廠開始提供登入(與身分驗證)機制服務。

也就是說,小網站你不用自己做登入和會員管理了,你連過來我這邊,我是大網站,我已經有幾百萬上億的用戶,(例如全台灣都用Line),而且早就做了超級安全的會員管理機制,你這小網站何必自己做會員管理呢?你跟我連結不就得了,我大網站來幫你管理個資,提供你登入的服務,你把會員資料通通存我這裡,用戶也不需要記得很多組帳密,只需要記得我大網站的帳密,一樣可以登入你小網站(或稱為第三方應用)來使用你提供的服務,這樣皆大歡喜。

因此,大家就這麼做了。

但提供這樣服務的大廠越來越多,Google、Microsoft、Yahoo…都提供了這樣的服務,導致小網站為了對使用者更貼心,可能要同時連結上很多這種提供身分服務的大網站,如果每一家連結方式都不同,就很煩。因此,業界就開了幾個會,共同決定了一套工業標準,就是OAuth了。

有哪些功能?

所以你會發現,基本上網站開發人員有兩種身分,一種是OAuth服務的提供者(像是Google、微軟、Line),另一種是OAuth服務的使用者,像是一般的小網站(trello)。而終端用戶只需要在大網站申請過帳號,就可以登入小網站來使用服務。

但,大網站當然不能給你(小網站)用戶的帳號和密碼,否則多麼不安全呢?因此OAuth工業標準讓服務提供者(大網站)透過一種標準的作法,在用戶驗證過身分之後,提供一組會過期的令牌給小網站,這就是token。

小網站拿著這個令牌,就可以跟大網站取得用戶的個資,或是其他需要的資料。小網站也可以拿著這個令牌,跟大網站確認該令牌是否已經到期。

所以,整個流程大概是底下這樣:

由於上述過程中的(2),登入畫面是大網站提供的,因此你小網站不會得知用戶的帳號密碼,大網站只會在登入成功後,把一個具有有效期限的Token傳給你小網站,一旦你需要存取用戶的資料,就拿這個token去跟大網站溝通。

當然,實際上的OAuth操作步驟又更複雜,如果你參考我們前面介紹的Line Login那篇,就會知道,用戶被引導到大網站完成登入之後,你小網站是無法直接取得token的,而是取得一個code,再去用這個code跟大網站換得一個token。為何要多這一道手續?因為,網際網路是個不安全的所在,在網路上傳遞的任何東西,都可能被路上經手的路由器或其他設備給擷取、偽造、變更,因此要確保安全,得更加小心一點。

因此一般的OAuth流程,其實應該長得像是底下這樣(這是微軟Graph API的OAuth Auth Authorization Code Flow流程) :

還有更複雜的、更進階的。

如果大網站除了提供用戶的個資之外,還要可以讓小網站有權限做一些額外的事情,像是變更用戶大頭照、取得用戶上傳的檔案、幫用戶book一個行事曆…這都是Office 365/Google Apps裡面典型的情境,如此一來,終端使用者(end-user)可能就要授權小網站,到底能夠使用該用戶在大網站中多少資料,也就是大網站的用戶要賦予小網站多大的權限,來存取該終端用戶的個資? 這部分,一般稱之為 Permission Scope。

所以,OAuth除了提供登入身分驗證之外,也逐漸開始負擔了網站合作之間的授權管理功能。

好,現在回過頭來看,請參考Line LoginLine Notify這兩篇中的例子,你會發現一開始我們都只是組出一個URL,來取得Authorization Code,這一段取得的code是明碼,走的是http get,透過瀏覽器網址列來傳遞,所以在網際網路上是可以被任何人擷取看到的(因此你當然應該加上SSL),但你會發現接下來小網站取得Authorization Code之後,要透過http post,從後端走另一個路徑去跟大網站換得token,這一段並不是走瀏覽器http get,而是在小網站的伺服器端走另一個https路徑,去跟大網站溝通。由於這一段往往是在背後做的(伺服器端對伺服器端,不會經過用戶端),因此安全性相對高(OAuth也有實作成在前端取token的implicit flow,但走後端相對安全點)。如果從後端換取Token,不管是瀏覽器或用戶本身都無法得知token,就算你的用戶被人在瀏覽器或電腦中安裝了木馬也無法得知,再加上Token還有期限,因此相對安全。

這也是我們前面說的,實務上小網站被導引到大網站完成登入之後,並非直接取得token而是取得一個Authorization Code的原因。

所以你也不難理解,既然Token會到期,就衍生出需要更新(refresh)token、判斷token的有效性、設定Token的生命長度…等相關議題,但在這邊就先不介紹了。

更進一步實現SSO

好的,假設網路世界的身分驗證,都是某一個大網站(例如Google)提供的,而其他服務的小網站(網站A、網站B、網站C…),都使用Google提供的身分驗證服務,那這世界就很單純了,一旦用戶登入了網站B,用著用著,連結到了網站A,還需要重新登入一次嗎? 不需要,因為在網站B已經登入過了,這就是SSO(Single Sign On)在internet上的實現。

一旦OAuth提供者和使用者(也就是大小網站),都有實作這樣的功能,那用戶翱翔於網際網路上時,就只需要記得一組帳號密碼了,這世界多麼美好…

當然,現實世界不是這樣的,你想想,當個大網站將會擁有所有人的個資耶,這意味著什麼呢? 不用大腦想也知道。 所以,只有你想做大網站? 不,每個人都想做。因此只要稍具規模網際網路服務提供者,都希望自己是最大的那個身分驗證提供者。

現在、連Line這個IM界的新玩家(相對What’s app、skype來說,真的算是新的),挾著在亞洲(其實也只有台灣、日本、和韓國…)的超人氣,都開始提供OAuth Provider服務了,你說,Line這家公司它還不夠任性嗎?
#搞懂了OAuth和SSO,不妨接著玩玩Line NotifyLine Login,很好玩唷… Smile
--------------------------------------------
如果需要即時取得更多相關訊息,可按這裡加入FB專頁。若這篇文章對您有所幫助,請幫我們分享出去,謝謝您的支持。

2016年12月31日 星期六

關於LineBot(7) - 使用Line Login實現oAuth SSO(單一登入)

上一篇寫完之後,我心裡想,我連Line Notify都寫了,那沒理由不寫Line Login吧,雖然,我猜不一定很多人對這個主題有興趣。

而且我覺得,要寫這個主題,我應該要先多寫一篇關於oAuth和SSO(Single Sign On)的文章才行,否則我覺得大半讀者可能如同到了北京一般(伸手不見五指)…不過,oAuth和SSO有空再寫,我先趁記憶猶新,把Line Login整理一下。(補充:後來寫了,請參考這裡)

背景與用途 : 基本上Line Login是讓網站或手機App開發人員做用戶身分識別(Identity)與單一登入(SSO)用的,也就是說,網站或手機App開發人員,不需要自己管理會員帳號密碼,可以透過Line Login這個符合oAuth標準的Identity機制,來進行用戶的身分驗證與個資取得,以達成單一登入。你一定曾經用過某些網站,在登入或註冊帳號的時候,並非要你填入新的帳密,而是連結(整合)到Google帳號或是微軟的Microsoft Account,即可完成身分驗證與登入。

這有什麼好處?

對用戶來說:

  1. 不用記得很多組帳號密碼

對網站或手機App開發人員來說

  1. 不用費心保管個資,由oAuth Provider(例如Google、以及本文要介紹的Line Login)幫你管理。
  2. 不用管個資,就沒有被竊的風險。
  3. 如果你有多個網站或服務,倘若都支援某一種驗證方式(例如Line Logic),則用戶登入了A網站,當連結到B網站的時候,無須再次登入(此即為SSO)。

好,我當作各位都知道了,如果對於oAuth或SSO還有疑問,以後有機會我再說明。我們先來看,要怎麼將你的網站連結到Line Login…

順帶一提,其實一直以來,Line的各種動作都看得出Line的企圖心不小,目前提供oAuth的廠商,幾乎各各是大廠,Google、微軟、Yahoo、沛米(不認識? 這是我投資參與的公司)…Line在這個領域要衝進來當玩家,很是任性…

註冊Line Login

在使用這個服務與你的網站整合前,你必須先註冊一個Line Login的服務,申請位置位於: https://business.line.me/zh-hant/services/login

(他說他有五億用戶耶…)
請給他按下去,一連串的動作之後,會出現底下這份表格:

有幾個填寫需要注意的地方:

  1. 上圖(1)的部分是你這個服務(網站、或app)的圖示,在要求用戶登入的畫面會出現。
  2. 上圖(2)的部分是你這個服務(網站、或app)的名稱,在要求用戶登入的畫面會出現。
  3. 上圖(3)的部分讓你選擇你是要在你自己的網站,或是你開發的App來使用這個服務,由於本文介紹的是一個網站的例子,因此請選擇Web。
  4. 這個是你的Line帳號 ID(或是你的帳號所註冊的公司的名稱),這無法改,它會在要求用戶登入的畫面出現。

填寫完畢之後,請按下確定,接著會出現一個我認為非常多餘的畫面,讓你確認資料是否正確,如果沒問題,請按下『申請』鈕:

按下申請,如果成功後,會出現底下的畫面,請留意只有Channel ID以後會用到,其他看看就好,然後直接按下右下角的綠色按鈕前往Line Developer網站:

當你按下上圖右下角的綠色按鈕前往Line Developer網站,之後,會出現底下畫面:

請注意,還有幾個地方要填寫,留意上圖左邊的選單,我們會用到(1)和(6)也就是選單的Basic Infomation和Technical Configration這兩個部分,Basic Infomation的部分就是上圖的畫面右半邊,請點選(2)的Edit,並且隨意把資料填寫完畢。然後按下上圖(4)的Show,取得一個重要的資訊,也就是Channel Secret。

至此,你會得到使用Line Login的兩個重要參數,一個是Channel ID,另一個是Channel Secret,它們長得像是底下這樣:
Channel ID : 1504723632 (這當然是假的)
Channel Secret : e2b481ca6ebd222aa653150c1c6375571444720232 (這當然也是假的)

接著,請按下上圖中的(6),會出現底下畫面,讓你設定Callback URL:

你可以點選上圖中的Edit,來設定Callback URL,由於我要在local測試,因此我輸入localhost的URL(如上圖)

說真的,如果你看到這邊覺得一頭霧水,我大概也猜的到為什麼。我自己也當過初學者,我一開始看oAuth和SSO的東西時,也不知道這到底是什麼意思。但久了之後,我就知道,為何以前看別人的貼文時,沒有多少人在解釋上面這些東西是什麼。因為,如果你知道oAuth的基本概念,上面這些根本不需要解釋,你甚至還會覺得我前面寫得太囉嗦。但,如果你不熟悉oAuth,上面這些解釋的再詳細也幫助不大…所以,我也就不解釋了,但我會盡快寫一篇oAuth和SSO的文章的,在我沒寫好之前,請先上網找找oAuth相關資料與概念,相信會有幫助( 補充: 請參考http://studyhost.blogspot.com/2017/01/oauthsso.html)

好,設定好了CallbackURL,並且取得Channel ID與Channel Secret之後,我們就已經擁有所有需要與Line Login整合的資訊了。接著就是如何開始實作…

開始將你的網站連結到Line Login

首先,請先建立底下這樣的網頁(有沒有,跟前面介紹Line Notify的時候好像):

請留意,上面程式碼中的11行裡面的redirect_uri必須和你在設定時設定的CallBackUrl相同(因為我在測試,因此是localhost),當你點選上圖的Button後,你會發現,頁面被導入到Line的登入畫面:

這個登入畫面是由Line提供的,因此你不會知道用戶的帳密,當用戶輸入正確的帳密之後,會出現底下的畫面,讓用戶確認,你提供的服務(網站或手機App)可以取得他的個資:

留意上圖中的(1)、(2),就是先前你設定時,輸入的服務名稱…

當用戶按下上圖中的『同意』鈕之後,會被導回你的CallbackUrl指定的頁面,並且在QueryString中傳遞了一個重要的Code:

請取得這個Code,我們要用該Code換取可以代表用戶的Token。後面我用postman示範,當你取得Code之後,你可以透過POST https://api.line.me/v1/oauth/accessToken ,並且傳遞底下的參數,來取得Token:

注意上圖中,我們透過POST呼叫,把Client_Id(1)、Client_Secret(2)以及相關參數傳遞給Line Login,Line Login則回傳(4)的Access_token給我們。

透過這個Token,我們就可以辨識用戶的身分,取得用戶的資料了,例如:

上面這個http get,將Token傳遞給Line,則Line回覆給我們用戶的displayName、mid、大頭照、以及StatusMessage。

透過這樣的方式,我們就實現了以Line Login提供的oAuth機制,來進行身分驗證的工作了,如此一來,我們自行開發的網站、App,就無需自行設計登入與會員管理機制,直接用Line Login提供的服務進行整合即可。

是不是很方便呢?(呵呵呵,我猜的到你的回答…)

官方文件在:
https://developers.line.me/web-api/integrating-web-login
https://devdocs.line.me/en/#how-to-use-the-apis

oAuth與SSO參考說明在 http://studyhost.blogspot.com/2017/01/oauthsso.html

--------------------------------------------
如果需要即時取得更多相關訊息,可按這裡加入FB專頁。若這篇文章對您有所幫助,請幫我們分享出去,謝謝您的支持。