更新2 这篇文章变老了,但仍然相关。下面是我解决它的方法。我标记了其他人的答案,因为我认为它更好地回答了问题。我在 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
}
然后,使用 facebok C# SDK 调用 facebook(如/me/home)的每个方法都会捕获 FacebookOAuthException 并重定向到以下方法。这就是我们应用最佳实践的方式,即不预先征求用户许可,而是在需要时征求用户许可。此方法也应具有匹配的重定向 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);
}
}
更新:此行为是由 .Net oauth 实现引起的,该实现的范围硬编码在密封类中。添加了图 4 以显示请求参数,其中除了“电子邮件”(由 .net oauth 提供程序随所有请求一起发送)之外缺少其他范围。将“,publish_stream”添加到查询字符串会给我想要的行为。任何人都知道如何实现这一点?
请不要提交有关 Facebook 最佳实践或替代解决方案的答案或评论。我有一个替代解决方案,但希望它可以使用默认的 registerfacebookclient 参数。我已根据指定我要求的权限的两个答案更新了应用程序以仅使用 publish_stream。
图 4
原始问题: 我正在设置一个应用程序(C#.Net4.5 MVC4,razor views),它需要来自 facebook 的几乎所有可用用户权限。 您可以在下面查看我如何设置所有内容的代码示例。
问题是,当单击图 1 中的“确定”时,Facebook 将我发送回我的应用程序。据我所知,应该有一个额外的屏幕(图 2)要求“更重”的权限。到目前为止,我只获得了图一中所述的权限。那部分工作...
图1
图2
所以,使用基本的 授权配置.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);
这就是我处理响应的方式,但这里 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 });
}
}
我能找到的最接近答案的是 wp 插件,它有同样的问题。他们的问题通过将域设置为本地主机来解决。这就是我的应用程序的设置方式。
最佳答案
我遇到了同样的问题。正如您所做的那样,我用字典配置了 RegisterFacebookClient 来定义我的应用程序的范围,但不幸的是,该请求不包括我配置的范围。所以我找到了that .这似乎行得通,但这还不够。所以我找到了this .
所以这是解决我的问题的方法:
首先,我将这个新客户端添加到我的代码中:
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;
}
}
}
我把它放在我的 asp.net 解决方案中的文件夹“infrastructure”中,接下来我更改我的旧配置,以便使用新的 facebook 客户端,如下所示:
旧代码:
OAuthWebSecurity.RegisterFacebookClient(
appId: "<app-id>",
appSecret: "<app-secret>",
displayName: "Facebook",
extraData: facebookExtraData);
新代码:
OAuthWebSecurity.RegisterClient(
new FacebookScopedClient(
"<app-id>",
"<app-secret>",
"scope"),
"Facebook",
null);
就是这样。它可能对您有所帮助,就像对我有所帮助一样。
关于c# - Facebook web 应用程序扩展权限第二步不显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16717002/
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
我想用ruby编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R