Mag*_*son 11 c# asp.net facebook facebook-c#-sdk asp.net-mvc-4
Update2 这篇文章已经老了但仍然相关..下面是我解决它的方式.我标记了其他人回答,因为我认为它更好地回答了这个问题.我在accountcontroller中调用了一个类似的方法(我将要重构:)).字符串应该是一个列表......我想你明白了.
/// <summary>
/// Use this method when an action fails due to lack of priviligies. It will redirect user to facebook with provided permission request.
/// Refactor to handle list of request.
/// </summary>
/// <param name="permission"></param>
private static void AddAdditionalPermissions(string permission)
{
System.Diagnostics.Trace.TraceInformation(permission + " not authorized for user.");
string facebook_urlAuthorize_base = "https://graph.facebook.com/oauth/authorize";
string scope = permission; //see: https://developers.facebook.com/docs/authentication/permissions/ for extended permissions
string urlAuthorize = facebook_urlAuthorize_base;
urlAuthorize += "?client_id=" + AppId;
urlAuthorize += "&redirect_uri=" + "https://fbd.anteckna.nu/";
urlAuthorize += "&scope=" + scope;
//redirect the users browser to Facebook to ask the user to authorize our Facebook application
HttpContext.Current.Response.Redirect(urlAuthorize, true); //this cannot be done using WebRequest since facebook may need to show dialogs in the users browser
}
Run Code Online (Sandbox Code Playgroud)
然后,使用facebok C#SDK调用facebook/you/home等每个方法捕获FacebookOAuthException并重定向到folling方法.这就是我们如何应用最佳实践,即不需要事先向用户请求权限,但需要时.此方法应该具有匹配的aredirect url但我们刚刚开始:)
希望能帮助到你!
/// <summary>
/// Check for what permissions to request or different ways to handle FacebookOAuthExceptions.
/// </summary>
/// <param name="foae">The exception object</param>
public static void HandleAuthorizationsExceptions(FacebookOAuthException foae)
{
if (foae.Message.Contains("publish_permissions"))
{
AddAdditionalPermissions("publish_permissions");
}
else if (foae.Message.Contains("read_stream"))
{
AddAdditionalPermissions("read_stream");
}
else
{
System.Diagnostics.Trace.TraceError("Unhandled error at:" + foae.StackTrace);
}
}
Run Code Online (Sandbox Code Playgroud)
更新:此行为是由.Net oauth实现引起的,其范围在密封类中进行了硬编码.添加了图4以显示除"email"之外缺少其他范围的请求参数(与.net oauth提供程序的所有请求一起发送).将",publish_stream"添加到查询字符串可以获得所需的行为.谁知道如何实现这一目标?
请不要提交有关Facebook最佳实践或替代解决方案的答案或评论.我有一个替代解决方案,但希望这与默认的registerfacebookclient参数一起使用.我已根据指定我要求的权限的两个答案更新了应用程序以使用publish_stream.
图4
原始问题: 我正在设置一个应用程序(C#.Net4.5 MVC4,razor views),它几乎需要来自facebook的所有可用用户权限.你可以在下面看到代码示例我如何设置它.
问题是,当点击图1中的"好"时,Facebook会将我发回给我的应用程序.据我所知,应该有一个额外的屏幕(图2)要求"更重"的权限.截至目前,我只获得了图1中所述的权限.那部分有用......
图1

图2

所以,使用基本的AuthConfig.cs
var facebooksocialData = new Dictionary<string, object>();
facebooksocialData.Add("scope", "email,publish_stream,read_stream,publish_actions,manage_pages,create_event,offline_access");
OAuthWebSecurity.RegisterFacebookClient(
appId: "165359673639901",
appSecret: "15091cb2094a1996ae6c7b324f0300e6",
displayName: "Facebook",
extraData: facebooksocialData);
Run Code Online (Sandbox Code Playgroud)
这就是我处理响应的方式,但是这里facebook没有提示用户提供扩展权限,但仅限于电子邮件,
AccountController.cs
//
// GET: /Account/ExternalLoginCallback
[AllowAnonymous]
public ActionResult ExternalLoginCallback(string returnUrl)
{
AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
if (!result.IsSuccessful)
{
return RedirectToAction("ExternalLoginFailure");
}
// Save the accesstoken into session
Session["accesstoken"] = result.ExtraData["accesstoken"];
Session["id"] = result.ExtraData["id"];
if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false))
{
return RedirectToLocal(returnUrl);
}
if (User.Identity.IsAuthenticated)
{
// If the current user is logged in add the new account
OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, User.Identity.Name);
return RedirectToLocal(returnUrl);
}
else
{
// User is new, ask for their desired membership name
string loginData = OAuthWebSecurity.SerializeProviderUserId(result.Provider, result.ProviderUserId);
ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(result.Provider).DisplayName;
ViewBag.ReturnUrl = returnUrl;
return View("ExternalLoginConfirmation", new RegisterExternalLoginModel { UserName = result.UserName, ExternalLoginData = loginData });
}
}
Run Code Online (Sandbox Code Playgroud)
最接近我能找到的答案是一个wp插件,它有同样的问题.他们的问题通过将域设置为localhost来解决.这就是我的应用程序的设置方式.![在此处输入图像说明] [4]
我遇到了同样的问题.正如您所做的那样,我使用字典配置了RegisterFacebookClient以定义我的应用程序范围,不幸的是,请求不包括我配置的范围.所以我发现了.这似乎有用,但还不够.所以我找到了这个.
所以这就解决了我的问题:
首先,我将这个新客户端添加到我的代码中:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using DotNetOpenAuth.AspNet;
using Newtonsoft.Json;
namespace MyApp.UI.Infrastructure
{
public class FacebookScopedClient : IAuthenticationClient
{
private string appId;
private string appSecret;
private string scope;
private const string baseUrl = "https://www.facebook.com/dialog/oauth?client_id=";
public const string graphApiToken = "https://graph.facebook.com/oauth/access_token?";
public const string graphApiMe = "https://graph.facebook.com/me?";
private static string GetHTML(string URL)
{
string connectionString = URL;
try
{
System.Net.HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(connectionString);
myRequest.Credentials = CredentialCache.DefaultCredentials;
//// Get the response
WebResponse webResponse = myRequest.GetResponse();
Stream respStream = webResponse.GetResponseStream();
////
StreamReader ioStream = new StreamReader(respStream);
string pageContent = ioStream.ReadToEnd();
//// Close streams
ioStream.Close();
respStream.Close();
return pageContent;
}
catch (Exception)
{
}
return null;
}
private IDictionary<string, string> GetUserData(string accessCode, string redirectURI)
{
string token = GetHTML(graphApiToken + "client_id=" + appId + "&redirect_uri=" + HttpUtility.UrlEncode(redirectURI) + "&client_secret=" + appSecret + "&code=" + accessCode);
if (token == null || token == "")
{
return null;
}
string access_token = token.Substring(token.IndexOf("access_token="), token.IndexOf("&"));
string data = GetHTML(graphApiMe + "fields=id,name,email,username,gender,link&" + access_token);
// this dictionary must contains
Dictionary<string, string> userData = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
return userData;
}
public FacebookScopedClient(string appId, string appSecret, string scope)
{
this.appId = appId;
this.appSecret = appSecret;
this.scope = scope;
}
public string ProviderName
{
get { return "facebook"; }
}
public void RequestAuthentication(System.Web.HttpContextBase context, Uri returnUrl)
{
string url = baseUrl + appId + "&redirect_uri=" + HttpUtility.UrlEncode(returnUrl.ToString()) + "&scope=" + scope;
context.Response.Redirect(url);
}
public AuthenticationResult VerifyAuthentication(System.Web.HttpContextBase context)
{
string code = context.Request.QueryString["code"];
string rawUrl = context.Request.Url.OriginalString;
//From this we need to remove code portion
rawUrl = Regex.Replace(rawUrl, "&code=[^&]*", "");
IDictionary<string, string> userData = 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");
AuthenticationResult result = new AuthenticationResult(true, ProviderName, id, username, userData);
return result;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我把它放在我的asp.net解决方案中的"基础设施"文件夹中,然后我改变了我的旧配置,以便使用新的facebook客户端,如下所示:
旧代码:
OAuthWebSecurity.RegisterFacebookClient(
appId: "<app-id>",
appSecret: "<app-secret>",
displayName: "Facebook",
extraData: facebookExtraData);
Run Code Online (Sandbox Code Playgroud)
新守则:
OAuthWebSecurity.RegisterClient(
new FacebookScopedClient(
"<app-id>",
"<app-secret>",
"scope"),
"Facebook",
null);
Run Code Online (Sandbox Code Playgroud)
而已.它可能对你有所帮助,对我有所帮助.
| 归档时间: |
|
| 查看次数: |
6228 次 |
| 最近记录: |