要避開使用Facebook JavaScript SDK,我找了一下,看來就是使用Server-Side Authentication這個方式才有辦法,這個server-side認證方式基本上是走OAuth 2.0的協定去跑,在2010時我已寫過文章"[Facebook] C# SDK Authentication"介紹過,串接方式蠻類似的,所以我就不會在這邊做過多介紹,不過上次沒貼code,這次會貼一下方便大家參考。
1. Redirect the user to the OAuth Dialog
第一步是將網頁轉到下面這個網址
https://www.facebook.com/dialog/oauth並帶下列參數
client_id : 應用程式的App ID。
redirect_uri : 認證後要導回的Url。
scope : 向使用者取得的授權。
state : (非必要)可自行運用的不重複字串。
2. The user is prompted to authorize your application
若使用者尚未授權此APP,或是scope有修改,則會出現下面畫面讓使用者確認。
3. The user is redirected back to your app
使用者授權的話,會向 redirect_uri 丟出下面參數回傳
state : 剛剛傳去的state(如果你有傳)
code : Facebook傳回產生的code
使用者拒絕的話,則會丟這些參數
error_reason=user_denied
error=access_denied
error_description=The+user+denied+your+request.
state : 剛剛傳去的state(如果你有傳)
像是這樣
4. Exchange the code for a user access token
取得code後,再將code連同下列參數丟到這網址去(不是redirect)
https://graph.facebook.com/oauth/access_tokenclient_id : 應用程式的App ID。
redirect_uri : 認證後要導回的Url(需與Step 1 一樣)。
client_secret : 應用程式的App Secret。
code : Facebook傳回產生的code
成功的話,該頁面會生出下列資訊,裡面就是我們所要的access_token與這個token的有效時間expries。
5. Make requests to the Graph API
有Access Token後,就可以去撈facebook上使用者有授權的資訊,如同範例上的連結這樣使用。
https://graph.facebook.com/me?access_token=YOUR_USER_ACCESS_TOKEN
最後就是範例啦,請記得要有Facebook C# SDK才能用
FBTest.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="FBTest.aspx.cs" Inherits="FBTest" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <script src='http://www.google.com/jsapi' type='text/javascript'></script> <script language='javascript' type='text/javascript'> google.load("jquery", "1.7.1");</script> <script type='text/javascript'> $(document).ready(function () { window.fbAsyncInit = function () { FB.init({ appId: 'YOUR_APP_ID', // App ID status: true, // check login status cookie: true, // enable cookies to allow the server to access the session xfbml: true // parse XFBML }); }; // Load the SDK Asynchronously (function (d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=YOUR_APP_ID"; fjs.parentNode.insertBefore(js, fjs); } (document, 'script', 'facebook-jssdk')); }); </script> </head> <body> <div id="fb-root"></div> <form id="form1" runat="server"> <div> <asp:Button ID="Button1" runat="server" Text="Auth" onclick="Button1_Click" /> <div class="fb-login-button" data-show-faces="true" data-width="400" data-max-rows="1"></div> <asp:Label ID="Label1" runat="server" Text=""></asp:Label> </div> </form> </body> </html>
FBTest.aspx.cs
using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Web; using Facebook; public partial class FBTest : System.Web.UI.Page { #region Props public string AppId = "YOUR_APP_ID"; public string AppSecret = "YOUR_APP_SECRET"; public string RedirectUri = "http://localhost:45353/WebTest/FBTest.aspx"; public string Scope = "email,publish_stream,user_photos"; public string ReturnCode { get { return (string.IsNullOrEmpty(Request.QueryString["code"])) ? null : Request.QueryString["code"]; } } public string ReturnError { get { return (string.IsNullOrEmpty(Request.QueryString["error"])) ? null : Request.QueryString["error"]; } } public int Stages { get { if (Session["AuthStage"] != null) return int.Parse(Session["AuthStage"].ToString()); else return (int)AuthStage.Initial; } set { Session["AuthStage"] = value; } } #endregion protected void Page_Load(object sender, EventArgs e) { if(Stages==(int)AuthStage.Initial) { if(!string.IsNullOrEmpty(ReturnCode)) { Stages = (int) AuthStage.GotCode; Session["AccessToken"] = GetAccessToken(); CallFb(); } if (!string.IsNullOrEmpty(ReturnError)) { Stages = (int)AuthStage.GotError; Label1.Text = "Error when user is redirected back"; } } } protected void Button1_Click(object sender, EventArgs e) { Stages = (int) AuthStage.Initial; string url = "https://www.facebook.com/dialog/oauth?client_id=" + AppId + "&redirect_uri=" + RedirectUri + "&scope="+Scope; Response.Redirect(url); } private void CallFb() { if (Session["AccessToken"] != null) { var accessToken = Session["AccessToken"].ToString(); var client = new FacebookClient(accessToken); try { dynamic result = client.Get("me", new { fields = "name,id,updated_time,picture" }); string name = result.name; string id = result.id; string updatedTime = result.updated_time; Label1.Text = name + " , " + id + " , " + updatedTime + " , " + result.picture; } catch (FacebookOAuthException ex) { Session.Remove("AccessToken"); HttpRuntime.Cache.Remove("access_token"); Label1.Text = (ex.Message.IndexOf("OAuthException - #190") > -1) ? "User has not authorized" : "unknow error"; } } else { var client = new FacebookClient(); dynamic me = client.Get("zuck"); string firstName = me.first_name; string lastName = me.last_name; Label1.Text = firstName + " , " + lastName; } } private Dictionary<string, string> GetOauthTokens(string code) { Dictionary<string, string> tokens = new Dictionary<string, string>(); string url = string.Format("https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&client_secret={2}&code={3}",AppId, RedirectUri, AppSecret, code); HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest; using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) { StreamReader reader = new StreamReader(response.GetResponseStream()); string retVal = reader.ReadToEnd(); Label1.Text += retVal; foreach (string token in retVal.Split('&')) { tokens.Add(token.Substring(0, token.IndexOf("=")), token.Substring(token.IndexOf("=") + 1, token.Length - token.IndexOf("=") - 1)); } } return tokens; } private string GetAccessToken() { if (HttpRuntime.Cache["access_token"] == null) { Dictionary<string, string> args = GetOauthTokens(Request.Params["code"]); HttpRuntime.Cache.Insert("access_token", args["access_token"], null, DateTime.Now.AddMinutes(Convert.ToDouble(args["expires"])), TimeSpan.Zero); } return HttpRuntime.Cache["access_token"].ToString(); } public enum AuthStage { Initial, GotCode, GotError, GotAccesstoken } }
貼出前我有稍微修改一下,應該還是會動啦。
No comments:
Post a Comment