我正在开发一个小型个人项目,用户可以通过{{loginButtons}}
内置的Meteor.js登录Facebook
但问题是,当通过apple-mobile-web-app-capable
全屏运行应用程序时,没有弹出对话框要求许可。屏幕空白。
我根本不使用facebook的sdk。
在手机游戏中效果很好。我已经将它部署到meteor进行最后的测试,所以它不是localhost问题。
这是否可以在不必创建我自己的用户创建和/或服务器端实现和/或facebook的sdk的情况下实现? 最终我计划添加更多内容,例如twitter和google。
另外,我还在使用iOS 6.1
答案 0 :(得分:3)
更新,请参阅我的其他答案以获得更多改进的示例
所以我花了大约一个小时搞清楚一些东西。 我认为最好的办法是放弃Meteor的内置帐户系统 相反,我正在使用'oauth.io'(没有隶属关系)和'流星路由器'而我将使用Meteor的Accounts.createUser()创建用户; 关于这个的最好的部分是,它适用于localhost和我的iPhone,所以我不必继续部署它来测试。
Meteor.startup(function () {
OAuth.initialize('my key');
});
我的路线:
Meteor.Router.add({
'/oauth': function() {
console.log('oauthed');
OAuth.callback('facebook', function(err, result) {
var token = result.access_token;
var url = 'https://graph.facebook.com/me?access_token='+token;
$.get( url, function( data ) {
alert(data.email)
console.log(data);
});
});
}
});
然后是一个简单的锚
$('#loginfb').live('click', function() {
OAuth.redirect('facebook', "/oauth");
});
就我而言,但它适用于apple-mobile-web-app-capable
我能够验证并获取我的Facebook信息。
它比我想做的工作更多,但并不太难。
所以我正在考虑做一些事情,比如用这个方法获取用户的电子邮件,然后使用:
Accounts.createUser({
email: data.email,
password: data.id //since your Facebook id can't change
});
这样用户可以稍后更改或重置它,或者我可以提示他们更改它。
然后我要检查该用户是否存在,(不知道该怎么做)以及是否存在然后执行:
Meteor.loginWithPassword(data.email, data.id);
确定。所以我稍微调整了我的设置。
我不得不切换到Backbone Router,出于某种原因,Meteor Router每次加载/ oauth时都会刷新页面两次。 Backbone没有。
我添加了一个用于生成密码的服务器端功能。
Meteor.startup(function () {
Backbone.history.start({
pushState: true,
root: "/"
});
OAuth.initialize('key goes here');
});
var $Router = Backbone.Router.extend({
routes: {
"/": "home",
"oauth": "oauth",
"": "home"
},
home: function () {
console.log('home')
},
oauth: function () {
OAuth.callback('facebook', function (err, result) {
console.log(result);
var token = result.access_token;
var url = 'https://graph.facebook.com/me?access_token=' + token;
$.get(url, function (data) {
var email = data.email;
var pass = Meteor.call('generatePass', data, function (error, result) {
Meteor.loginWithPassword(email, result, function (error) {
if (error) {
var options = {};
options.email = email;
options.password = pass;
Accounts.createUser(options, function (error) {
if (error) {
console.log(error);
$router.navigate('/');
} else {
//Account creation successful return to index
$router.navigate('/');
}
})
} else {
//Login successful return to index
$router.navigate('/');
}
});
});
});
return false;
});
}
});
var $router = new $Router();
// I use jquery for events, I don't like to use meteor's template event handlers.
$('#loginfb').click(function (event) {
event.preventDefault();
//have to use redirect, otherwise popup won't work correctly since we're using mobile-webapp-capable
OAuth.redirect('facebook', "/oauth");
});
//server.js
Meteor.methods({
generatePass: function (data) {
// .. do stuff ..
var pass = fancy function that creates a password based on the supplied data;
return pass;
}
});
到目前为止它只适用于Facebook,而且测试不是很好。 我喜欢一些指导和/或建设性的批评。
答案 1 :(得分:1)
问题似乎是oauth包使用window.open打开一个弹出窗口。我之前没有使用过apple-mobile-web-app的经验,但有些研究似乎暗示window.open无法使用它。如果客户端使用可以使用
的全屏应用程序,该解决方案似乎正在测试window.navigator.standalone
不幸的是,oauth登录工作流程在假设已打开弹出窗口时有点尴尬。我不确定进行此测试的最佳位置在哪里,以及在用户在新窗口中输入用户名/密码后是否会尝试登录或创建用户。
我尝试将window.open方法更改为accounts-oauth-helper / oauth_client.js中的window.location然后打开窗口,但我的redirect_uri问题可能是因为我在localhost项目上执行此操作从我的手机,所以我不确定登录过程后登录过程是否会继续。
在使用apple-mobile-web-app-capable时,这似乎会影响所有登录提供商,因此这可能是一个需要修复的错误。我稍后会尝试设置一个项目,以便更好地了解它并告诉您它是如何进行的。
答案 2 :(得分:1)
我想出了一个更好的方法来做到这一点,而不使用帐户Facebook和没有使用Facebook自己的sdk 但是我正在使用流星的帐户和帐户 - ui(不是我真的需要它,它只是方便)
客户端上的事件处理程序
Template.header.events({
'click #loginFB': function(e) {
e.preventDefault();
OAuth.redirect('facebook', "/oauthlink");
//or
var url = 'https://www.facebook.com/dialog/oauth?client_id=' +client_id+'&response_type=token&redirect_uri='+redirect;
window.location = url;
}
});
铁路由器从OAuth获取结果的路线
this.route('oauthLink', {
path: '/oauthlink',
action: function() {
OAuth.callback('facebook', function(err, result) {
Meteor.call('fblogin', result, function(error, result) {
Meteor.loginWithToken(result.token, function(err) {
if(err) {
Meteor._debug("Error logging in with token: " + err);
}
})
});
});
}
});
或没有oauth.io
this.route('oauthLink', {
path: '/oauthlink',
action: function() {
var str = window.location.hash;
str = str.split('&');
var accessToken = str[0];
var expiresIn = str[1];
accessToken = accessToken.split('=');
expiresIn = expiresIn.split('=');
var result = {
access_token : accessToken[1],
expires_in : expiresIn[1]
};
Meteor.call('fblogin', result, function(error, result) {
console.log(result)
Meteor.loginWithToken(result.token, function(err) {
if(err) {
Meteor._debug("Error logging in with token: " + err);
}
})
});
}
});
不确定'Action'是否是正确的功能(我是铁路由器的新手),但它确实有效。
然后在服务器上
Meteor.methods({
fblogin: function(response) {
var identity = Meteor.call('$getIdentity', response.access_token);
// synchronous call to get the user info from Facebook
var serviceData = {
accessToken: response.access_token,
expiresAt: (+new Date) + (1000 * response.expires_in)
};
// include all fields from facebook
// http://developers.facebook.com/docs/reference/login/public-profile-and-friend-list/
var whitelisted = ['id', 'email', 'name', 'first_name',
'last_name', 'link', 'username', 'gender', 'locale', 'age_range'];
var fields = _.pick(identity, whitelisted);
_.extend(serviceData, fields);
var stuff = {
serviceName : 'facebook',
serviceData: serviceData,
options: {profile: {name: identity.name}}
};
var userData = Accounts.updateOrCreateUserFromExternalService(stuff.serviceName, stuff.serviceData, stuff.options);
var x = DDP._CurrentInvocation.get();
var token = Accounts._generateStampedLoginToken();
Accounts._insertLoginToken(userData.userId, token);
Accounts._setLoginToken(userData.userId, x.connection, Accounts._hashLoginToken(token.token))
x.setUserId(userData.userId)
return {
id: userData.userId,
token: token.token,
tokenExpires: Accounts._tokenExpiration(token.when)
};
},
$getIdentity: function(accessToken) {
try {
return HTTP.get("https://graph.facebook.com/me", {
params: {access_token: accessToken}}).data;
} catch (err) {
throw _.extend(new Error("Failed to fetch identity from Facebook. " + err.message),
{response: err.response});
}
}
});
几乎所有fblogin()实际上都来自Meteor自己的accounts-facebook包。 我只是修改它以满足我的需要。 $ getIdentity是来自那里的逐字副本。
var stuff包含Facebook数据(名称,访问令牌等)和流星帐户数据,并将其放入Accounts.updateorcreateuserfromexternalservice,用于构建您的流星帐户 fblogin()返回userData,它从Accounts.updateorcreate ....获取,然后从中获取您的令牌,您可以通过Metoer.loginWithToken登录。
所有这些都是在不打开新窗口或标签的情况下发生的,就像我使用accounts-facebook一样。因此,修复我的主要问题,并作为额外的奖励,它似乎在功能上等同于使用accounts-facebook。 不再检查用户是否存在,如果是,登录,使用“生成的密码”,或者如果它们不存在,则创建它们,然后使用“生成的密码”登录
当然,这可以扩展到其他oauth apis,你显然不需要oauth.io。我只是懒惰。 希望其他人认为这很有用。