我们有:
(1)与Facebook OAuth的功能(以下简称“FB网络应用程序”)的Facebook基于API的Web应用
(2) UIWebView
的基于浏览器在iPad(“浏览器”)
我们的目标是打开Facebook登录页面登录到FB Web应用程序(1)在iPad上的基于UIWebView中的浏览器(2)内。
这里有几分相似的问题:
http://facebook.stackoverflow.com/questions/11337285/no-longer-able-to-login-to-ios-app-via-oauth-the-page-requested-was-not-found
然而,这一问题的问题发生在用户输入登录名和密码后进入Facebook的形式。 我们的问题是,我们不能在第一时间显示在Facebook的登录表单。 从“网络”的“本地/桌面”更改应用程序类型,在这个问题的建议,并没有帮助。
脚步:
1.本打开我们的网页(简单的HTML页面) UIWebView
浏览器
2.点击“FB的Web应用程序”启动按钮在此页
3. JavaScript的的OnClick试图发起OAuth的,应打开了Facebook的登录屏幕登录到FB的Web应用程序
目前的结果(问题):
在iOS 5. +和iOS 6. +设备
- 我们的网页保持不变
- Facebook登录页面不显示(我们的网页仍然显示)
在iOS 4.3(按预期工作):
- Facebook登录页面是在同一个打开UIWebView
浏览器的对象(取代我们的网页)
预期结果:
显示Facebook登录页面,用户可以输入Facebook登录和密码 -
- 如果在iPad上的Safari浏览器推出了iOS上的5 +和iOS 6 +作品。 Facebook登录页面在一个单独的标签打开(相比之下,在没有单独的选项卡UIWebView
)
问:我怎样才能得到UIWebView
响应于iOS上的OAuth请求5+和iOS 6+打开Facebook登录页面?
更多的技术细节:
我们登录不同NSURLRequest
从内场
-(BOOL)webView(UIWebView*)webView shouldStartLoadWithRequest(NSURLREquest*)request navigationType:…
我们注意到了“正确”和“不正确”的行为日志中的一些差异。 这里是如何执行流帮我看一下:
首先,我按“FB Web App的”起动按钮来启动的OAuth,那么某些情况下,去
的iOS 4.3,“正确的”
请求www.facebook.com/dialog/oauth?...
请求fbwebapp.com
请求m.facebook.com/login.php?....
--here Facebook登录出现
的iOS 5.0,“incorrect1”
请求www.facebook.com/dialog/oauth?...
请求fbwebapp.com
请求m.facebook.com/login.php?...
然后,它可能是
--a很多m.facebook.com/login.php?...with的下一个...在参数
其次是sqlite的错误
--right现在我明白了“对不起,出事了”页面从Facebook(这是第一次在所有我遇到它)
的iOS 6.0“incorrect2”
请求www.facebook.com/dialog/oauth?...
请求fbwebapp.com
- (无效)web视图:(的UIWebView *)webView的didFailLoadWithError:(NSError *)错误被调用,错误代码-999
你可以看到,行为的确依赖于IOS版本。 但常见的情况是获得m.facebook.com/login.php .. URL的步骤发生的错误。 但是,这一切,我们可以检测到。
我们正在敲打我们的头抵住墙一整天寻找解决方案。 绝望。
你能帮助我们在打开Facebook登录页面UIWebView
响应OAuth的?
Answer 1:
只需使用:此代码
if (![FBSDKAccessToken currentAccessToken])
{
FBSDKLoginManager *manager = [[FBSDKLoginManager alloc]init];
manager.loginBehavior = FBSDKLoginBehaviorWeb;
[manager logInWithReadPermissions:@[@"public_profile", @"email", @"user_friends"] handler:
^(FBSDKLoginManagerLoginResult *result, NSError *error) {
NSLog(@"result.token: %@",result.token.tokenString);
NSLog(@"%@",result.token.userID);
NSLog(@"%hhd",result.isCancelled);
}];
}
//这里manager.loginBehavior = FBSDKLoginBehaviorWeb;
是所有你需要在打开的Facebook UIWebview
Answer 2:
做到了!
它有点黑客攻击,但Facebook的JS SDK登录在一个UIWebView在iOS 6中的最后作品。
如何才能做到? 它是一个纯JS + JS的Facebook SDK + UIWebView的代表处理功能的解决方案。
JS - 第一步)
登录按钮(以连接Facebook)调用此函数例如,将触发面部JS登录/ OAuth的对话框:
function loginWithFacebookClick(){
FB.login(function(response){
//normal browsers callback
});
}
JS - 第二步)
添加authResponseChange听众每次用户加载网页(后FB.init())来捕捉用户的连接状态:
FB.Event.subscribe('auth.authResponse.Change', function(response){
//UIWebView login 'callback' handler
var auth = response.authResponse;
if(auth.status == 'connected'){
//user is connected with facebook! just log him at your webapp
}
});
并与应用程序的UIWebView的委托功能,你可以处理程序的Facebook的OAuth回应
目标C - 第三步)将
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString *url = [[request URL] absoluteString];
//when user status == connected (has a access_token at facebook oauth response)
if([url hasPrefix:@"https://m.facebook.com/dialog/oauth"] && [url rangeOfString:@"access_token="].location != NSNotFound)
{
[self backToLastPage];
return NO;
}
return YES;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSString *url = [[webView.request URL] absoluteString];
if([url hasPrefix:@"https://m.facebook.com/dialog/oauth"])
{
NSString *bodyHTML = [webView stringByEvaluatingJavaScriptFromString:@"document.body.innerHTML"];
//Facebook oauth response dead end: is a blank body and a head with a script that does
//nothing. But if you got back to your last page, the handler of authResponseChange
//will catch a connected status if user did his login and auth app
if([bodyHTML isEqualToString:@""])
{
[self backToLastPage];
}
}
}
所以,当“重定向”用户最后加载页面,第二步是要在Facebook登录对话框到处理器的用户操作。
如果我得到了这样的回答太快,请问我! 希望能帮助到你。
Answer 3:
如果有人在谷歌上搜索,这里是为我工作:
-(BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)inType {
if ([request.URL.absoluteString containsString:@"m.facebook.com"]) {
if ([request.URL.absoluteString rangeOfString:@"back"].location == 0) {
[self.popUp removeFromSuperview];
self.popUp = nil;
return NO;
}
if (self.popUp) {
return YES;
}
UIWebView *wv = [self popUpWebView];
[wv loadRequest:request];
return NO;
}
return YES;
}
- (UIWebView *) popUpWebView {
toolbar height
UIWebView *webView = [[UIWebView alloc]
initWithFrame:CGRectMake(0, 0, (float)self.view.bounds.size.width,
(float)self.view.bounds.size.height)];
webView.scalesPageToFit = YES;
webView.delegate = self;
// Add to windows array and make active window
self.popUp = webView;
[self.view addSubview:webView];
return webView;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
if (self.popUp) {
NSError *error = nil;
NSString *jsFromFile = @"window.close=function(){window.location.assign('back://' + window.location);};";
__unused NSString *jsOverrides = [webView
stringByEvaluatingJavaScriptFromString:jsFromFile];
JSContext *openerContext = [self.webView
valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
JSContext *popupContext = [webView
valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
popupContext[@"window"][@"opener"] = openerContext[@"window"];
}
//this is the secret sauce
if (webView == self.popUp
&& [webView.request.URL.absoluteString containsString:@"m.facebook.com"]
&& [[webView stringByEvaluatingJavaScriptFromString:@"document.body.innerHTML"] isEqualToString:@""]) {
[webView stringByEvaluatingJavaScriptFromString:@"eval(document.getElementsByTagName('script')[0].text)"];
}
}
我钩住了一堆这种实现的从这里 。
根据您的网络的实施,将有可能是一个额外的步骤。 Facebook的脚本实际执行window.close()
再window.open()
然后window.close()
。 对我来说这是造成问题,因为在网络侧,在此之后登录完成后,我的窗口(即,我希望用户登录到web视图)是获得一个window.close()
调用,从Facebook的SDK来。 我假设这是因为Facebook的SDK预计window.open()
调用打开一个新的窗口将关闭。
由于我们没有覆盖的功能window.open()
调用window.open()
不会做任何事情,而Facebook的SDK会尝试关闭窗口。 这可能会导致各种各样的问题,但对我来说,因为我使用的解析, window.localStorage
设置为null
,所以我让所有类型的错误。
如果这样的事情发生了你,你有两种选择来解决它:
- 如果你的网页代码控制,和你的小黑客下来,扔在这个
window.close=function(){}
- 如果你没有的网页代码控制,您可以添加替代到
window.close
像我们一样的弹出webView的主web视图,或者重写window.open
函数打开另一个弹出(其描述这里更详细 )
Answer 4:
使用FBDialog类来提示用户登录。 这对成功登录,用户在任何一个UIWebView的内部记录使用网页视图的应用内,因此:
NSString *kRedirectURL = @"fbconnect://success";
NSString *kSDK = @"ios" ;
NSString *kLogin = @"oauth";
NSString *kDialogBaseURL = @"https://m.facebook.com/dialog/";
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
AE_FACEBOOK_APPID, @"client_id",
@"user_agent", @"type",
kRedirectURL, @"redirect_uri",
@"touch", @"display",
kSDK, @"sdk",
nil];
NSString *loginDialogURL = [kDialogBaseURL stringByAppendingString:kLogin];
FBLoginDialog* loginDialog = [[FBLoginDialog alloc] initWithURL:loginDialogURL
loginParams:params
delegate:self];
[loginDialog show];
然后,让你的类坚持FBDialogDelegate协议,而这个功能添加到您的类:
-(void)fbDialogLogin: (NSString *)token expirationDate:(NSDate *)expirationDate{
// Store the token and expiration date into the FB SDK
self.facebook.accessToken = token;
self.facebook.expirationDate = expirationDate;
// Then persist these so the SDK picks them up on next load
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:self.facebook.accessToken forKey:ACCESS_TOKEN_KEY];
[defaults setObject:self.facebook.expirationDate forKey:EXPIRATION_DATE_KEY];
[defaults synchronize];
}
HTH!
Answer 5:
如何Facebook登录在UIWebView的。
Objective-C的
使用taylorstine的答案 。 他救了我的一天。 谢谢taylorstine
但是我用斯威夫特3.所以我只是转换下面的代码从taylorstine的答案。
斯威夫特3。
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if let _ = request.url?.absoluteString.range(of: "m.facebook.com" ) {
if let _ = request.url?.absoluteString.range(of: "back"){
self.popUp?.removeFromSuperview()
self.popUp = nil
return false
}
if let _ = self.popUp {
return true
}
let wv = popUpWebView()
wv.loadRequest(request)
return false
}
return true
}
func popUpWebView() -> UIWebView {
let webView = UIWebView(frame: self.view.frame)
webView.delegate = self
self.popUp = webView
self.view.addSubview(webView)
return webView
}
func webViewDidFinishLoad(_ webView: UIWebView) {
if let _ = self.popUp {
let jsFromFile = "window.close=function(){window.location.assign('back://' + window.location);};"
let _ = webView.stringByEvaluatingJavaScript(from: jsFromFile)
let openerContext = self.webView.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as! JSContext
let popupContext = webView.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as! JSContext
popupContext.setObject("opener", forKeyedSubscript: "window" as (NSCopying & NSObjectProtocol)!)
popupContext.setObject(openerContext.objectForKeyedSubscript("window"), forKeyedSubscript: "opener" as (NSCopying & NSObjectProtocol)!)
}
if webView == self.popUp
&& (webView.request?.url?.absoluteString.range(of:"m.facebook.com") != nil)
&& webView.stringByEvaluatingJavaScript(from: "document.body.innerHTML") == "" {
webView.stringByEvaluatingJavaScript(from: "eval(document.getElementsByTagName('script')[0].text)")
}
}
文章来源: How can I get UIWebView to open Facebook login page in response to the OAuth request on iOS 5 and iOS 6?