ASP.NET MVC通過OAuth調用Google API獲取用戶信息


一邊享受着鄉村的寧靜,一邊寫着博客,也是一種愜意。

喜歡解決問題后寫一篇博客。通過文字表達出來,會加深自己的理解,還經常會有新的收獲,甚至會找到更好的解決方法。同時,還能分享給別人。一舉多得,何樂而不為呢?

這次要解決的問題是如何在用戶注冊時驗證用戶的郵箱?

通常的解決方法是給用戶的郵箱發一封激活郵件。但這個方法有以下幾個問題:

  • 從發出郵件至收到郵件,可能會有延時。
  • 郵件可能會被當作垃圾郵件處理
  • 用戶可能會填錯了郵箱,更糟糕的情況是用戶不知道自己填錯了郵箱。

這次要解決的問題的更具體的場景是如何驗證用戶的gmail郵箱?

我們采用的解決方法是通過OAuth調用Google API獲取用戶的gmail地址

於是,問題就變為如何在ASP.NET MVC中通過OAuth調用Google API

必看的兩個文檔:

Using OAuth 2.0 to Access Google APIs

Using OAuth 2.0 for Web Server Applications

我們的OAuth應用場景是Web Server Applications,對應的序列圖如下:

簡單描述一下整個流程:

  1. 你在網站上提供一個Google OAuth登錄的鏈接
  2. 用戶點擊這個鏈接進入Google登錄頁面進行登錄
  3. 用戶登錄成功后,會顯示授權頁面。
  4. 用戶授權成功后,Google會自動重定向至你的網站頁面,並傳遞authorization code給你。
  5. 通過這個authorization code,向Google OAuth服務器請求access_token。
  6. 拿到access_token之后,調用Google API獲取用戶信息。

下面是具體的實現步驟:

1. 進入Google APIs Console,創建一個Project,並創建Client ID,如下圖:

得到這些信息 —— Client ID, Email address, Client secret, Redirect URIs

2. 創建一個空的ASP.NET MVC項目

3. 在web.config中添加相應的appSetting保存第1步得到的Client ID相關信息

<appSettings>
    <add key="ClientID" value=""/>
    <add key="EmailAddress" value=""/>
    <add key="ClientSecret" value=""/>        
    <add key="RedirectURI" value=""/>      
</appSettings>

4. 創建MVC控制器OAuthController,並添加名為GoogleLogin的Action,用於重定向至Google頁面進行登錄。代碼如下:

public class OAuthController : Controller
{
    public ActionResult GoogleLogin()
    {
        var url = "https://accounts.google.com/o/oauth2/auth?"+
            "scope={0}&state={1}&redirect_uri={2}&response_type=code&client_id={3}&approval_prompt=force";
        //userinfo.email表示獲取用戶的email
        var scope = HttpUtility.UrlEncode("https://www.googleapis.com/auth/userinfo.email");
        //對應於userinfo.email
        var state = "email";
        var redirectUri = HttpUtility.UrlEncode(ConfigurationManager.AppSettings["RedirectURI"]);
        var cilentId = HttpUtility.UrlEncode(ConfigurationManager.AppSettings["ClientID"]);
        return Redirect(string.Format(url, scope, state, redirectUri, cilentId));
    }
}

編譯后,通過瀏覽器訪問,假設域名是passport.cnblogs.cc,訪問網址就是passport.cnblogs.cc/oauth/googlelogin,訪問后,如果你的google帳戶已經處於登錄狀態,則直接顯示授權頁面,如下圖:

點擊"Allow access"之后,頁面會被重定向回你的網站,我們這里重定向過來的網址是passport.cnblogs.cc/oauth2callback?state=email&code=4/BSCUqsaY6S5GYk9tFR-45-_UhL4-,查詢參數code的值就是authorization code,接下來就是對這個重定向網址passport.cnblogs.cc/oauth2callback的處理(這個網址就是第1步中得到的Redirect URIs)。

5. 在Global.asax.cs中添加路由規則,代碼如下:

routes.MapRoute(
    "oauth2callback",
    "oauth2callback",
    new { controller = "OAuth", action = "GoogleCallback", id = UrlParameter.Optional }
);

6. 在OAuthController中添加名為GoogleCallback的Action

public class OAuthController : Controller
{
    public ActionResult GoogleCallback()
    {
    }
}

接下來的操作都在GoogleCallback()中完成。

7.  這一步是關鍵的地方,主要完成兩個操作:

a) 通過authorization code,向Google OAuth服務器請求access_token(訪問令牌,每次調用Google API都需要這個)。
b) 拿到access_token之后,調用Google API獲取用戶信息(這里是email)。

主要參考文檔:https://developers.google.com/accounts/docs/OAuth2WebServer

7.1 根據authorization code獲取access_token的代碼流程是:

  • 向https://accounts.google.com/o/oauth2/token發送HTTP POST請求,並傳遞相應的參數。
  • 獲取服務器的響應,響應內容的格式時json格式。
  • 將json反序列化為匿名類型的實例,並獲取access_token。

代碼如下:

//由於是https,這里必須要轉換為HttpWebRequest
var webRequest = WebRequest.Create("https://accounts.google.com/o/oauth2/token") as HttpWebRequest;
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";

//參考https://developers.google.com/accounts/docs/OAuth2WebServer
var postData = string.Format("code={0}&client_id={1}&client_secret={2}&redirect_uri={3}" +
    "&grant_type=authorization_code",
    Request.QueryString["code"],
        ConfigurationManager.AppSettings["ClientID"],
        ConfigurationManager.AppSettings["ClientSecret"],
        ConfigurationManager.AppSettings["RedirectURI"]);

//在HTTP POST請求中傳遞參數
using (var sw = new StreamWriter(webRequest.GetRequestStream()))
{
    sw.Write(postData);
}

//發送請求,並獲取服務器響應
var resonseJson = "";
using (var response = webRequest.GetResponse())
{
    using (var sr = new StreamReader(response.GetResponseStream()))
    {
        resonseJson = sr.ReadToEnd();
    }
}

//通過Json.NET對服務器返回的json字符串進行反序列化,得到access_token
var accessToken = JsonConvert.DeserializeAnonymousType(resonseJson, new { access_token = "" }).access_token;

7.2 根據access_token讀取用戶信息的代碼流程是:

  • 向https://www.googleapis.com/oauth2/v1/userinfo發送HTTP GET請求,在請求頭中包含access_token信息。
  • 獲取服務器的json格式的響應內容,並從中讀取用戶的email信息。

代碼如下:

webRequest = WebRequest.Create("https://www.googleapis.com/oauth2/v1/userinfo") as HttpWebRequest;
webRequest.Method = "GET";
webRequest.Headers.Add("Authorization", "Bearer " + accessToken);

using (var response = webRequest.GetResponse())
{
    using (var sr = new StreamReader(response.GetResponseStream()))
    {
        return Content(JsonConvert.DeserializeAnonymousType(sr.ReadToEnd(), new { Email = "" }).Email);
    }
}

完整代碼下載

http://files.cnblogs.com/dudu/CNBlogsDemoMvcOAuth.rar 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM