【ASP.net MVC】專案放置 Facebook 登入-- OAuth 認證(3)

【ASP.net MVC】專案放置 Facebook 登入-- OAuth 認證(3)
前一篇,已經跟各位說明如何透過範本建立Facebook的驗證,但是取得的資料有限,可能有部分網站只需要幾項註冊資訊就可以使用了,但是可能比較複雜的註冊網站,可能需要出生日期、所在地點、性別...的資料,此時內建的驗證所取得的資料就不太符合我們的需求了!所以,這邊接下來要讓使用者登入Facebook帳號後,直接取得使用者的資訊!雖然這個可以利用讓使用者後續透過輸入的方式處理,但是通常使用者很懶得再去輸入這些資料。
接下來,我們需要去撰寫一些程式碼,才有辦法達到我們所要求的資料(當然,還是使用者按下同意按鈕,才有辦法取得)!
首先,我們需要把底層的OAuth的驗證做些修改((這些修改,幾乎把我們要用的類別都改寫了...)),以下是小弟在網路上搜尋到的程式碼,部分有稍作修改,並且加入了註解,以供閱讀!

前一篇,已經跟各位說明如何透過範本建立Facebook的驗證,但是取得的資料有限,可能有部分網站只需要幾項註冊資訊就可以使用了,但是可能比較複雜的註冊網站,可能需要出生日期、所在地點、性別...的資料,此時內建的驗證所取得的資料就不太符合我們的需求了!所以,這邊接下來要讓使用者登入Facebook帳號後,直接取得使用者的資訊!雖然這個可以利用讓使用者後續透過輸入的方式處理,但是通常使用者很懶得再去輸入這些資料。

接下來,我們需要去撰寫一些程式碼,才有辦法達到我們所要求的資料(當然,還是使用者按下同意按鈕,才有辦法取得)!

 

首先,我們需要把底層的OAuth的驗證做些修改((這些修改,幾乎把我們要用的類別都改寫了...)),以下是小弟在網路上搜尋到的程式碼,部分有稍作修改,並且加入了註解,以供閱讀!

原始連結請點這

 


public class FacebookScopedClient : IAuthenticationClient
{
    private string appId;
    private string appSecret;

    //設置基礎連結,顯示驗證視窗的對話方塊
    private const string BaseUrl = "https://www.facebook.com/dialog/oauth?client_id=";
    //設置基礎連結,取得Token
    public const string GraphApiToken = "https://graph.facebook.com/oauth/access_token?";
    //設置基礎連結,取得使用者資料
    public const string GraphApiMe = "https://graph.facebook.com/me?";

    /// <summary>
    /// 【私用】取得要求頁面的網頁資訊
    /// </summary>
    /// <param name="URL">要求的連結</param>
    /// <returns></returns>
    private static string GetHTML(string URL)
    {
        string ConnectionString = URL;

        try
        {
            // 向對方Server傳送要求
            System.Net.HttpWebRequest MyRequest = (HttpWebRequest)WebRequest.Create(ConnectionString);
            MyRequest.Credentials = CredentialCache.DefaultCredentials;
            //// 取得網站的回應
            WebResponse WebResponse = MyRequest.GetResponse();
            Stream ResponeStream = WebResponse.GetResponseStream();
            ////開啟資料讀取串流
            StreamReader IOStream = new StreamReader(ResponeStream);
            string PageContent = IOStream.ReadToEnd();
            //// 關閉串流
            IOStream.Close();
            ResponeStream.Close();
            return PageContent;
        }
        catch (Exception)
        {
        }
        return null;
    }

    /// <summary>
    /// 解析使用者資料
    /// </summary>
    /// <param name="AccessCode">資料授權碼</param>
    /// <param name="RedirectURI">返回的頁面連結</param>
    /// <returns></returns>
    private IDictionary<string, string> GetUserData(string AccessCode, string RedirectURI)
    {
        //取得授權Token
        string Token = GetHTML(GraphApiToken + "client_id=" + appId + "&redirect_uri=" + HttpUtility.UrlEncode(RedirectURI) + "&client_secret=" + appSecret + "&code=" + AccessCode);
        if (Token == null || Token == "")//若Token是null或空白,表示驗證失敗
        {
            return null;
        }
        //向Facebook傳送要求,取得使用者資料,fields則放置你所需要的資料
        string Data = GetHTML(GraphApiMe + "fields=id,name,email,username,gender,link,birthday&access_token=" + Substring(Token, "access_token=", "&"));

        //解析Facebook傳回的使用者資料,Facebook傳回的是Json格式的資料,我們這邊利用Json.net這個套件解析Json
        //Json.net則可以透過NuGet取得
        Dictionary<string, string> UserData = JsonConvert.DeserializeObject<Dictionary<string, string>>(Data);
        return UserData;
    }


    /// <summary>
    /// 初始化
    /// </summary>
    /// <param name="appId">授權代碼</param>
    /// <param name="appSecret">授權安全碼</param>
    public FacebookScopedClient(string appId, string appSecret)
    {
        this.appId = appId;
        this.appSecret = appSecret;
    }

    /// <summary>
    /// 傳回供應商名稱
    /// </summary>
    public string ProviderName
    {
        get { return "Facebook"; }
    }

    /// <summary>
    /// 導向Facebook驗證授權頁面
    /// </summary>
    /// <param name="Context">Http要求資訊</param>
    /// <param name="ReturnUrl">通過授權後導回的頁面</param>
    public void RequestAuthentication(System.Web.HttpContextBase Context, Uri ReturnUrl)
    {
        string Url = BaseUrl + appId + "&redirect_uri=" + HttpUtility.UrlEncode(ReturnUrl.ToString()) + "&scope=email,user_birthday,user_location,publish_actions";
        Context.Response.Redirect(Url);
    }

    /// <summary>
    /// 傳回授權狀態與授權資料
    /// </summary>
    /// <param name="Context">Http要求資訊</param>
    /// <returns>授權狀態與授權資料</returns>
    public AuthenticationResult VerifyAuthentication(System.Web.HttpContextBase Context)
    {
        string Code = Context.Request.QueryString["code"];

        string RawUrl = Context.Request.Url.OriginalString;

        RawUrl = Regex.Replace(RawUrl, "&code=[^&]*", "");

        IDictionary<string, string> UserData = this.GetUserData(Code, RawUrl);

        //假如使用者資訊為空白,就傳回驗證失敗
        if (UserData == null)
            return new AuthenticationResult(false, ProviderName, null, null, null);

        string id = UserData["id"];
        string UserName = UserData["username"];
        UserData.Remove("id");
        UserData.Remove("username");

        return new AuthenticationResult(true, ProviderName, id, UserName, UserData);
    }

    /// <summary>
    /// 私用,擷取部分字串資料
    /// </summary>
    /// <param name="Str">原始字串</param>
    /// <param name="StartString">開始擷取的字串內容</param>
    /// <param name="EndString">結束擷取的字串內容</param>
    /// <returns>原始字串的內容</returns>
    private string Substring(string Str, string StartString, string EndString)
    {
        if (Str.Contains(StartString))
        {
            int iStart = Str.IndexOf(StartString) + StartString.Length;
            int iEnd = Str.IndexOf(EndString, iStart);
            return Str.Substring(iStart, (iEnd - iStart));
        }
        return null;
    }
}

既然我們已經準備好了Facebook可以自訂使用者資料的類別了,接下來我們要去設定AuthConfig.cs的OAuth的認證

我們的類別不是微軟所提供的,所以我們使用RegisterClient,來註冊我們的Facebook登入


OAuthWebSecurity.RegisterClient(new FacebookScopedClient("appId", "appSecret"), "Facebook", null);

至於我們原本範本建立出來的Controllers,其實不需要太大的更改,除非有特別的需求,才需要稍作修改

其實要寫出一個Facebook驗證,並不會太困難!

 

檔案下載:

FacebookScopedClient下載

 

參考資料:

Facebook權限要求設定:https://developers.facebook.com/docs/reference/login/open-graph-permissions/

Facebook Graph API Explorer:https://developers.facebook.com/tools/explorer

 

本篇相關:

OAuth(一)  

OAuth(二)

 


 

大家好我是饅頭,希望大家喜歡我的文章

如果有錯誤的地方請不吝指教 ^_^