作業中の ASP.NET Web サイトに Facebook のログインと登録を実装しましたが、最適なプロセスがあるかどうかはわかりません。コメント/修正は大歓迎です。開発プロセスが少しばらばらであることがわかりました... facebook はパズルのピースを提供しますが、ピースがどのように組み合わされるかについては不十分です。これが私がやった方法です: -
マスターページ:-
<!doctype html>
<%--facebook namespace needed for xfbml ...--%>
<html xmlns:fb="http://ogp.me/ns/fb#">
Facebook SDK と Facebook ログイン JavaScript 関数を含めるスクリプト。ASP.NET アプリにポストバックして、Facebook の電子メールをデータベースのユーザー テーブルと照合します。ご覧のとおり、Facebook の UserID はコメント アウトされています。これは、使用した表記法で抽出できなかったためです。(これを行う方法についてのアイデアはありますか?) :-
<%--the fb-root div is used by the facebook sdk and the like plugin further below the sdk load --%>
<div id="fb-root"></div>
<%--facebook javascript SDK--%>
<script type="text/javascript">
// Load the SDK Asynchronously
(function(d){
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
}(document));
// Init the SDK upon load
window.fbAsyncInit = function() {
FB.init({
appId : 'XXXXXXXXXXXXX', // App ID
channelUrl : '//'+window.location.hostname+'/channel.htm', // Path to your Channel File
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
}
// catch Facebook login button press
function FacebookLogin() {
// user has auth'd your app and is logged into Facebook
FB.api('/me', function(response) {
// Do a post to the server to finish the logon
// This is a form post since we don't want to use AJAX
var form = document.createElement("form");
form.setAttribute("method", 'post');
form.setAttribute("action", '/RegistrationFacebookTestForUser.aspx');
// var field = document.createElement("input");
// field.setAttribute("type", "hidden");
// field.setAttribute("name", 'fbuserid');
// field.setAttribute("value", response.authResponse.userID);
// form.appendChild(field);
var field2 = document.createElement("input");
field2.setAttribute("type", "hidden");
field2.setAttribute("name", 'tempform_email');
field2.setAttribute("value", response.email.toString());
form.appendChild(field2);
document.body.appendChild(form);
form.submit();
});
}
</script>
フォームは RegistrationFacebookTestForUser.aspx.cs にポストバックされ、ユーザーの facebook メールをデータベースと照合します:-
public partial class RegistrationFacebookTestForUser : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//fbid.Text = Request.Form["fbuserid"];
email.Text = Request.Form["tempform_email"];
// get user from facebook email
MembershipUser tempUser = Membership.GetUser(Request.Form["tempform_email"]);
if (tempUser == null) // if user not found redirect to Facebook Registration Page
{
Response.Redirect("~/RegistrationFacebook.aspx");
}
else // if user found set auth cookie and redirect
{
FormsAuthentication.SetAuthCookie(tempUser.UserName, true);
Response.Redirect(Request.UrlReferrer.ToString());
}
}
}
電子メールが見つからない場合は、RegistrationFacebook.aspx にリダイレクトして、Facebook 登録プラグイン経由で登録を提供します....
RegistrationFacebook.aspx:-
<div id="facebook_registration" runat="server">
<iframe src="https://www.facebook.com/plugins/registration.php?
client_id=110835352327502&
redirect_uri=http://localhost/RegistrationFacebookBackend.aspx&
fields=
[
{'name':'name'},
{'name':'first_name'},
{'name':'last_name'},
{'name':'email'},
{'name':'password'},
{'name':'_business', 'description':'Do you work for ?', 'type':'select', 'options':{'':'I do not work for ','f5f064ad-0db4-42ce-ba86-e65e6d262768':'xxxxxxxx','534d6c7b-6c3a-4b7d-a41c-9e240c199f1d':'xxxxxxxx'}},
{'name':'network', 'description':'Please select your region', 'type':'select', 'options':{'a':'a','b':'b','c':'c','d':'d','e':'e','f':'f','g':'g','h':'h','i':'i','j':'j','k':'k','l':'l','96e9b78a-cc3b-4c6e-b4e4-bc0ba18184c1':'UK','521199a2-5847-4ec0-bca1-19052a110da8':'South Africa'}},
{'name':'public_profile', 'description':'Make my profile public so other users can see me', 'type':'checkbox', 'default':'checked'},
{'name':'newsletter', 'description':'Please send me the monthly Unite newsletter', 'type':'checkbox'},
{'name':'sponsor_email', 'description':'Please email me when someone sponsors me', 'type':'checkbox', 'default':'checked'},
{'name':'tandc', 'description':'I confirm that I have read and accepted the Terms and Conditions', 'type':'checkbox'}
]
"
scrolling="auto"
frameborder="no"
style="border:none"
allowTransparency="true"
width="100%"
height="530">
</iframe>
</div>
登録Facebook.aspx.cs :-
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
// its a save of content in admin mode
}
else
{
// RegistrationFacebookBackend has redirected back here after creating the user
if (!String.IsNullOrEmpty(Request.QueryString["facebook_result"]))
{
switch (Request.QueryString["facebook_result"])
{
case "Success":
CreateAccountResultsSuccess.Text = "You have successfully registered with Unite and the Unite Facebook app!";
CreateAccountResultsSuccess.Visible = true;
facebook_registration.Visible = false;
break;
case "InvalidUserName":
CreateAccountResultsError.Text = Resources.Error_Registration_InvalidUserName;
CreateAccountResultsError.Visible = true;
break;
case "DuplicateUserName":
CreateAccountResultsError.Text = Resources.Error_Registration_DuplicateUserName;
CreateAccountResultsError.Visible = true;
break;
case "DuplicateEmail":
CreateAccountResultsError.Text = Resources.Error_Registration_DuplicateEmail;
CreateAccountResultsError.Visible = true;
break;
case "InvalidEmail":
CreateAccountResultsError.Text = Resources.Error_Registration_InvalidEmail;
CreateAccountResultsError.Visible = true;
break;
case "InvalidPassword":
CreateAccountResultsError.Text = Resources.Error_Registration_InvalidPassword;
CreateAccountResultsError.Visible = true;
break;
default:
CreateAccountResultsError.Visible = true;
CreateAccountResultsError.Text = Resources.Error_Registration_Default;
break;
}
}
}
}
}
RegistrationFacebook.aspx の登録プラグインは、RegistrationFacebookBackend.aspx にポストバックして、ユーザーを ASP.NET アプリに登録します。ここで注目すべき主なことは、Page_Load での Facebook フォームの signed_request 変数のデコードと、メンバーシップとプロファイルの作成です。ここでは CachedMembershipProvider を使用しますが、ここでは通常のメンバーシップ プロバイダー コードに置き換えるだけです。(networkGUID はアプリの一部にすぎないため、無視してください:-
public partial class RegistrationFacebookBackend : System.Web.UI.Page
{
private UserService userService;
private MembershipUser newUser;
private string userName; private string email; private string password; private string firstname; private string lastname;
private string _business; private string network; private string location;
private bool newsletter; private bool sponsor_email;
//private Guid networkId;
#region public properties
public UserService UserService
{
get { return userService ?? (userService = new UserService()); }
}
public MembershipUser NewUser
{
get { return newUser ?? (newUser = Membership.GetUser(userName)); }
}
#endregion
/// <summary>
/// Handles the Load event of the Page control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
//
}
else // Request with Facebook signed_request payload ... create the user
{
if (!string.IsNullOrEmpty(Request.Form["signed_request"]))
{
string payload = Request.Form["signed_request"].Split('.')[1];
var encoding = new UTF8Encoding();
var decodedJson = payload.Replace("=", string.Empty).Replace('-', '+').Replace('_', '/');
var base64JsonArray = Convert.FromBase64String(decodedJson.PadRight(decodedJson.Length + (4 - decodedJson.Length % 4) % 4, '='));
var json = encoding.GetString(base64JsonArray);
var o = JObject.Parse(json);
userName = o.SelectToken("registration.email").ToString().Replace("\"", "");
email = o.SelectToken("registration.email").ToString().Replace("\"", "");
password = o.SelectToken("registration.password").ToString().Replace("\"", "");
firstname = o.SelectToken("registration.first_name").ToString().Replace("\"", "");
lastname = o.SelectToken("registration.last_name").ToString().Replace("\"", "");
_business = o.SelectToken("registration._business").ToString().Replace("\"", "");
network = o.SelectToken("registration.network").ToString().Replace("\"", "");
location = o.SelectToken("user.country").ToString().Replace("\"", "");
newsletter = (o.SelectToken("registration.newsletter").ToString().Replace("\"","") == "checked") ? true : false;
sponsor_email = (o.SelectToken("registration.sponsor_email").ToString().Replace("\"","") == "checked") ? true : false;
MembershipCreateStatus createStatus;
CachedMembershipProvider cmp = new CachedMembershipProvider();
System.Collections.Specialized.NameValueCollection nvc = new System.Collections.Specialized.NameValueCollection();
nvc.Add("providerName","AspNetSqlMembershipProvider");
cmp.Initialize("CachedMembershipProvider", nvc );
newUser = cmp.CreateUser(userName, password, email, null, null, true, Guid.NewGuid(), out createStatus);
switch (createStatus)
{
case MembershipCreateStatus.Success:
// set roles and create profile
SetUserProfile(true);
FormsAuthentication.SetAuthCookie(newUser.UserName, true);
Response.Redirect("RegistrationFacebook.aspx?facebook_result=Success");
break;
case MembershipCreateStatus.InvalidUserName:
Response.Redirect("RegistrationFacebook.aspx?facebook_result=InvalidUserName");
break;
case MembershipCreateStatus.DuplicateUserName:
Response.Redirect("RegistrationFacebook.aspx?facebook_result=DuplicateUserName");
break;
case MembershipCreateStatus.DuplicateEmail:
Response.Redirect("RegistrationFacebook.aspx?facebook_result=DuplicateEmail");
break;
case MembershipCreateStatus.InvalidEmail:
Response.Redirect("RegistrationFacebook.aspx?facebook_result=InvalidEmail");
break;
case MembershipCreateStatus.InvalidPassword:
Response.Redirect("RegistrationFacebook.aspx?facebook_result=InvalidPassword");
break;
default:
Response.Redirect("RegistrationFacebook.aspx?facebook_result=error_default");
break;
}
}
else // Request WITHOUT Facebook signed_request payload
{
}
}
}
/// <summary>
/// Gets the user profile.
/// </summary>
/// <param name="profileUserName">Name of the user.</param>
/// <returns></returns>
private Web.WebProfile GetUserProfile(string profileUserName)
{
ProfileBase wp = Web.WebProfile.Create(profileUserName);
return new Web.WebProfile(wp);
}
/// <summary>
/// Sets the user profile.
/// </summary>
private void SetUserProfile(bool createEvents)
{
if (newUser == null)
{
throw new ArgumentNullException("newUser");
}
//Control container = CreateUserWizard1.CreateUserStep.ContentTemplateContainer;
Web.WebProfile newProfile = GetUserProfile(NewUser.UserName);
newProfile.UserId = (Guid)NewUser.ProviderUserKey;
newProfile.FirstName = firstname;
newProfile.LastName = lastname;
newProfile.EmailAddress = email;
newProfile.NetworkId = NetworkGuid;
newProfile.FurtherInformationOptIn = true;
newProfile.Location = location;
newProfile.IsTemporary = false;
newProfile.OptInFavourites = false;
newProfile.OptInNewsletters = newsletter;
newProfile.OptInGiveTimeEvents = false;
newProfile.OptInFundraisers = sponsor_email;
newProfile.OptInNews = false;
newProfile.Save();
newProfile = new WebProfile(WebProfile.Create(NewUser.UserName));
UserService.CreateNewProfilePage(newProfile, false);
if (createEvents)
{
EventService ues = new EventService();
IEvent ue = ues.CreateEvent(EventType.Registration, newProfile.NetworkId, newProfile.UserId,
newProfile.UserId);
}
}
protected Guid NetworkGuid
{
get
{
Guid networkGuid;
if (Convertors.GuidTryParse(_business, out networkGuid) == true)
{
return networkGuid; // if they have selected a business that is the one to use
}
else if (Convertors.GuidTryParse(network, out networkGuid) == true)
{
return networkGuid; // otherwise use the region they have selected
}
else
{ //otherwise default to UK
Convertors.GuidTryParse("96e9b78a-cc3b-4c6e-b4e4-bc0ba18184c1", out networkGuid);
return networkGuid;
}
}
}
}