Facebook 社群身分驗證
這個專案一開始執行,只會有一個按鈕,當按下這個按鈕,就會使用原生平台的功能,進行 OAuth2 的身分驗證;當驗證過程結束之後,會將取得的 Token 顯示在螢幕上。
建立社群身分驗證頁面方案
- 首先,開啟您的 Visual Studio 2015
- 接著透過 Visual Studio 2015 功能表,選擇這些項目
檔案
>新增
>專案
準備新增一個專案。 - 接著,Visual Studio 2015 會顯示
新增專案
對話窗,請在這個對話窗上,進行選擇Visual C#
>Cross-Platform
>Blank Xaml App (Xamarin.Forms Portable)
- 接著,在最下方的
名稱
文字輸入盒處,輸入XFAuth
這個名稱,最後使用滑鼠右擊右下方的確定
按鈕。 - 當專案建立到一半,若您的開發環境還沒有建置與設定完成 Mac 電腦與 Xamarin Studio for Mac 系統,此時會看到
Xamarin Mac Agent Instructions
對話窗出現,這個對話窗是要提醒您進行與 Mac 電腦連線設定,這是因為,您無法在 Windows 作業系統進行 iOS 相關應用程式的建立與設計工作,而是需要透過 Mac 電腦安裝的 XCode 來協助您完成這些 iOS 應用程式的建立工作。不過,這不影響您繼續開發 Xamarin.Forms 的應用程式,只不過此時,您無法編譯與執行 iOS 的應用程式。 - 接著會看到
新的通用Windows專案
對話視窗,此時,您只需要按下確定
按鈕即可,此時,專案精靈會繼續完成相關平台的專案建立工作。 - 最後,整個新的 Xamarin.Forms 專案就建立完成了。
安裝所需 NuGet 套件
- 請在
XFAuth.Droid
專案的參考
節點上,滑鼠右擊,接著點選管理 NuGet 套件
選項,接著點選瀏覽
標籤頁次,在搜尋文字輸入盒中,輸入Xamarin.Auth
這個套件,當找到這個套件之後,請將這個套件安裝到這個專案裡面。 - 請在
XFAuth.iOS
專案的參考
節點上,滑鼠右擊,接著點選管理 NuGet 套件
選項,接著點選瀏覽
標籤頁次,在搜尋文字輸入盒中,輸入Xamarin.Auth
這個套件,當找到這個套件之後,請將這個套件安裝到這個專案裡面。
核心PCL頁面新增
OAuthMessage
這個檔案是用來作為訊息中心的指定型別之用
- 滑鼠右擊核心PCL
XFAuth
專案,點選加入
>類別
>Visual C#
>類別
- 在底下名稱欄位內輸入
OAuthMessage
,之後,點選新增
按鈕 - 請將底下程式碼覆蓋掉這個檔案所有內容
OAuthMessage.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XFAuth
{
public class OAuthMessage
{
}
}
LoginPage
現在要新增的檔案,是用於當要進行 Facebook 身分驗證的時候,所要顯示的頁面;雖然,這個頁面內沒有任何定義,不過,當執行時期,這個頁面將會由原生平台定義的視覺內容,注入到這個頁面中。
- 滑鼠右擊核心PCL
XFAuth
專案,點選加入
>類別
>Visual C#
>類別
- 在底下名稱欄位內輸入
LoginPage
,之後,點選新增
按鈕 - 請將底下程式碼覆蓋掉這個檔案所有內容
- 這個建構式接受一個列舉參數,用來指名所要進行的身分驗證是要採用哪個社群,相關社群的驗證參數,都會儲存在
ProviderOAuthSettings
物件內。
LoginPage.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace XFAuth
{
public class LoginPage : ContentPage
{
public OAuthSettings ProviderOAuthSettings { get; set; }
public LoginPage(Provider provider)
{
ProviderOAuthSettings = ProviderManager.GetProviderOAuthSettings(provider);
}
}
}
OAuthSettings
這個檔案將會定義
OAuthSettings
類別,裡面的屬性將會用來記錄要進行 OAuth2 身分驗證時,會用到的內容。- 滑鼠右擊核心PCL
XFAuth
專案,點選加入
>類別
>Visual C#
>類別
- 在底下名稱欄位內輸入
OAuthSettings
,之後,點選新增
按鈕 - 請將底下程式碼覆蓋掉這個檔案所有內容
.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XFAuth
{
public class OAuthSettings
{
public string ClientId { get; set; }
public string ClientSecret { get; set; }
public string AuthorizeUrl { get; set; }
public string RedirectUrl { get; set; }
public string AccessTokenUrl { get; set; }
public List<string> Scopes { get; set; }
public string ScopesString
{
get
{
return Scopes.Aggregate((current, next) => string.Format("{0}+{1}", current, next));
}
}
public OAuthSettings()
{
Scopes = new List<string>();
}
}
}
ProviderManager
這個類別提供一個靜態方法
GetProviderOAuthSettings
,根據所指定的社群定義,傳回該社群已經定義好的相關參數- 滑鼠右擊核心PCL
XFAuth
專案,點選加入
>類別
>Visual C#
>類別
- 在底下名稱欄位內輸入
ProviderManager
,之後,點選新增
按鈕 - 請將底下程式碼覆蓋掉這個檔案所有內容
- 若要使用 Facebook 來進行身分驗證,您需要在 Facebook 中產生一個應用程式,並且取得該應用程式上的
應用程式編號
,應用程式密鑰
;當然,要到到時候可以讓使用者充分識別這是哪個Facebook應用程式的身分驗證,可以在顯示名稱
欄位輸入明確說明這個應用程式的文字。
ProviderManager.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XFAuth
{
public enum Provider
{
Unknown = 0,
Facebook,
Google
}
public static class ProviderManager
{
private static OAuthSettings FacebookOAuthSettings
{
get
{
return new OAuthSettings
{
ClientId = "1651918068462476",
ClientSecret = "b9e46e4c7257b8c6e108dad79df603d3",
AuthorizeUrl = "https://m.facebook.com/dialog/oauth/",
RedirectUrl = "http://www.facebook.com/connect/login_success.html",
AccessTokenUrl = "https://graph.facebook.com/v2.3/oauth/access_token",
Scopes = new List<string> {
""
}
};
}
}
private static OAuthSettings GoogleOAuthSettings
{
get
{
return new OAuthSettings
{
ClientId = "",
ClientSecret = "",
AuthorizeUrl = "https://accounts.google.com/o/oauth2/auth",
RedirectUrl = "https://www.googleapis.com/plus/v1/people/me",
AccessTokenUrl = "https://accounts.google.com/o/oauth2/token",
Scopes = new List<string> {
"openid"
}
};
}
}
public static OAuthSettings GetProviderOAuthSettings(Provider provider)
{
switch (provider)
{
case Provider.Facebook:
{
return FacebookOAuthSettings;
}
case Provider.Google:
{
return GoogleOAuthSettings;
}
}
return new OAuthSettings();
}
}
}
MainPage
修改應用程式首頁頁面內容與 code behind 的程式碼
- 在核心PCL
XFAuth
專案,打開MainPage.xaml
- 請將底下程式碼覆蓋掉這個檔案所有內容
- 在這個 XAML 檔案內,定義了一個按鈕,按下後,會切換到 Facebook 的身分驗證頁面,而其他的
Label
控制項,則是用來顯示身分驗證的成功與取消的內容。
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XFAuth"
x:Class="XFAuth.MainPage">
<ContentPage.Padding>30</ContentPage.Padding>
<StackLayout
Orientation="Vertical"
VerticalOptions="Center" HorizontalOptions="Center"
>
<Button
x:Name="button登入Facebook"
Text="登入Facebook"
/>
<Label
x:Name="labelToken"
Text="Token"
IsVisible="False"
/>
<Label
x:Name="labelTokenValue"
Text=""
LineBreakMode="WordWrap"
IsVisible="False"
/>
<Label
x:Name="labelTokenError"
Text=""
TextColor="Red"
LineBreakMode="WordWrap"
IsVisible="False"
/>
</StackLayout>
</ContentPage>
- 在核心PCL
XFAuth
專案,打開MainPage.xaml.cs
- 請將底下程式碼覆蓋掉這個檔案所有內容
- 底下程式碼定義了一個按鈕處理事件,另外,也使用訊息中心的
MessagingCenter.Subscribe
訂閱了一個訊息事件,用來聆聽身分驗證的結果,並且做出相關處理。
MainPage.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace XFAuth
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
button登入Facebook.Clicked += async (s, e) =>
{
await Navigation.PushModalAsync(new LoginPage(Provider.Facebook));
};
MessagingCenter.Subscribe<OAuthMessage, string>(this, "Authenticated", (sender, e) =>
{
var foo = new Button();
button登入Facebook.IsVisible = false;
labelToken.IsVisible = true;
var fooResult = e as string;
if (fooResult == "Canceled!" )
{
labelToken.Text = "使用者中斷";
labelTokenError.Text = "使用者取消登入Facebook";
labelTokenError.IsVisible = true;
labelTokenValue.IsVisible = false;
}
else if (fooResult.Contains("Authentication Exception"))
{
labelToken.Text = "Exception";
labelTokenError.Text = fooResult;
labelTokenError.IsVisible = true;
labelTokenValue.IsVisible = false;
}
else
{
labelToken.Text = "Token";
labelTokenValue.Text = fooResult;
labelTokenValue.IsVisible = true;
labelTokenError.IsVisible = true;
}
});
}
}
}
Android 原生專案
您需要在原生專案內做些修正。
LoginPageRenderer
- 滑鼠右擊
XFAuth.Droid
專案,點選加入
>類別
>Visual C#
>Class
- 在底下名稱欄位內輸入
LoginPageRenderer
,之後,點選新增
按鈕 - 請將底下程式碼覆蓋掉這個檔案所有內容
- 這個類別使用了
ExportRenderer
屬性,用來定在當LoginPage
頁面要出現在 Android 平台的時候,需要客製化的相關畫面內容。 - 若需要使用
Xamarin.Auth
套件來進行 OAuth2 身分驗證,您需要產生OAuth2Authenticator
這個物件,定義相關處理事件,最後,呼叫auth.GetUI
方法,將驗證畫面顯示在螢幕上。 - 在不同驗證處理結果的事件上,將會透過訊息中心提供的
MessagingCenter.Send<OAuthMessage, string>
方法,將處理結果透過訊息中心傳送出去;而此時,在核心PCL專案內的首頁頁面內的 code behind 程式碼,就會接收到這個訊息事件。
LoginPageRenderer.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Xamarin.Forms;
using XFAuth;
using Xamarin.Forms.Platform.Android;
using XFAuth.Droid;
using Xamarin.Auth;
[assembly: ExportRenderer(typeof(LoginPage), typeof(LoginPageRenderer))]
namespace XFAuth.Droid
{
public class LoginPageRenderer : PageRenderer
{
LoginPage page;
bool loginInProgress;
public LoginPageRenderer()
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
{
base.OnElementChanged(e);
if (e.OldElement != null ||
Element == null)
return;
page = e.NewElement as LoginPage;
if (page == null ||
loginInProgress)
return;
loginInProgress = true;
try
{
OAuth2Authenticator auth = new OAuth2Authenticator(
page.ProviderOAuthSettings.ClientId, // your OAuth2 client id
page.ProviderOAuthSettings.ClientSecret, // your OAuth2 client secret
page.ProviderOAuthSettings.ScopesString, // scopes
new Uri(page.ProviderOAuthSettings.AuthorizeUrl), // the scopes, delimited by the "+" symbol
new Uri(page.ProviderOAuthSettings.RedirectUrl), // the redirect URL for the service
new Uri(page.ProviderOAuthSettings.AccessTokenUrl));
auth.AllowCancel = true;
auth.Completed += async (sender, args) => {
if (args.IsAuthenticated)
{
var token = args.Account.Properties["access_token"];
MessagingCenter.Send<OAuthMessage, string>(new OAuthMessage(), "Authenticated", token);
}
else
{
MessagingCenter.Send<OAuthMessage, string>(new OAuthMessage(), "Authenticated", "Canceled!");
}
await page.Navigation.PopModalAsync();
loginInProgress = false;
};
auth.Error += (sender, args) =>
{
Console.WriteLine("Error: {0}", args.Exception);
};
var activity = this.Context as Activity;
activity.StartActivity(auth.GetUI(activity));
}
catch (Exception ex)
{
MessagingCenter.Send<OAuthMessage, string>(new OAuthMessage(), "Authenticated", $"Authentication Exception: {ex.Message}");
}
}
}
}
iOS 原生專案
您需要在原生專案內做些修正。
LoginPageRenderer
- 滑鼠右擊
XFAuth.iOS
專案,點選加入
>類別
>Apple
>類別
- 在底下名稱欄位內輸入
LoginPageRenderer
,之後,點選新增
按鈕 - 請將底下程式碼覆蓋掉這個檔案所有內容
LoginPageRenderer.cs
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Auth;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using XFAuth;
using XFAuth.iOS;
[assembly: ExportRenderer(typeof(LoginPage), typeof(LoginPageRenderer))]
namespace XFAuth.iOS
{
public class LoginPageRenderer : PageRenderer
{
LoginPage page;
bool loginInProgress;
public LoginPageRenderer()
{
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.OldElement != null ||
Element == null)
return;
page = e.NewElement as LoginPage;
}
public override async void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
if (page == null ||
loginInProgress)
return;
loginInProgress = true;
try
{
OAuth2Authenticator auth = new OAuth2Authenticator(
page.ProviderOAuthSettings.ClientId, // your OAuth2 client id
page.ProviderOAuthSettings.ClientSecret, // your OAuth2 client secret
page.ProviderOAuthSettings.ScopesString, // scopes
new Uri(page.ProviderOAuthSettings.AuthorizeUrl), // the scopes, delimited by the "+" symbol
new Uri(page.ProviderOAuthSettings.RedirectUrl), // the redirect URL for the service
new Uri(page.ProviderOAuthSettings.AccessTokenUrl));
auth.AllowCancel = true;
// If authorization succeeds or is canceled, .Completed will be fired.
auth.Completed += async (sender, args) => {
if (args.IsAuthenticated)
{
var token = args.Account.Properties["access_token"];
MessagingCenter.Send<OAuthMessage, string>(new OAuthMessage(), "Authenticated", token);
}
else
{
MessagingCenter.Send<OAuthMessage, string>(new OAuthMessage(), "Authenticated", "Canceled!");
}
await DismissViewControllerAsync(true);
await page.Navigation.PopModalAsync();
loginInProgress = false;
};
auth.Error += (sender, args) =>
{
Console.WriteLine("Error: {0}", args.Exception);
};
await PresentViewControllerAsync(auth.GetUI(), true);
}
catch (Exception ex)
{
MessagingCenter.Send<OAuthMessage, string>(new OAuthMessage(), "Authenticated", $"Authentication Exception: {ex.Message}");
}
}
}
}
實際執行畫面
Android 執行結果
請在方案總管內,滑鼠右擊
XFAuth.Droid
專案,選擇 設定為起始專案
,接著按下 F5
開始執行。iOS 執行結果
請在方案總管內,滑鼠右擊
XFAuth.iOS
專案,選擇 設定為起始專案
,接著按下 F5
開始執行。
Xamarin.Auth
,進行社群身分驗證,在這裡,將會使用 Facebook 作為身分驗證的來源。