我正在尝试创建一个使用Steam API的程序。我希望能够调用该方法从客户端检索用户的信息,同时保持方法的实际代码对客户端保密,因为它包含API密钥。我尝试在服务器文件夹中将方法定义为全局,如下所示:
key = 'xxxxxxxxxxxxxxxx';
Meteor.steamFunctions = {
getName: function(user){
var userSteamId = user.profile.id;
Meteor.http.get('http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=' + key + '&steamids=' + userSteamId, function(error, resultJSON){
if (error){
return 'Error in Steam API';
} else {
var json = JSON.parse(resultJSON);
return json.personaname;
}
})
},
getPic: function(user){
var userSteamId = user.profile.id;
Meteor.http.get('http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=' + key + '&steamids=' + userSteamId, function(error, resultJSON){
if (error){
return 'Error in Steam API';
} else {
var json = JSON.parse(resultJSON);
return json.avatarfull;
}
})
}
}
然后我尝试在客户端脚本中调用它:
if (Meteor.isClient){
Template.profile.helpers({
'getName': function(){
return Meteor.steamFunctions.getName(Meteor.user());
}
});
}
然而,这会抛出
Exception in template helper: TypeError: Cannot read property 'getName' of undefined
at Object.Template.profile.helpers.getName
如何在仍然访问数据的同时保持对用户的密钥保密?
答案 0 :(得分:2)
嗯,这并不像向Meteor
全局添加属性那么简单。此外,执行此操作的远程方法/调用API将涉及异步代码。
使用秘密API密钥在服务器端调用API,只能在服务器上看到代码,例如: ./server
子目录。在服务器端定义Meteor.method,可以在客户端使用Meteor.call进行调用。
在服务器端Meteor方法中,您可以method security checks检查登录的用户或用户ID,并使用此方法来决定是进行呼叫还是忽略请求。如果请求不正确或出现错误,您可以从服务器端抛出新的Meteor.Error,但这些需要资源进行通信。
关于Meteor的理解是,改变Javascript在浏览器或服务器上的行为方式并没有什么神奇之处。服务器最终运行nodejs。在服务器上定义的对象不会神奇地迁移到客户端,反之亦然。如果在两者上定义了一个对象,它实际上是两个独立的代码片段。
因此,在客户端代码中,从浏览器调用服务器端代码的Meteor.call
实际上是使用本质上异步的现有websocket或ajax API。这意味着您需要构建客户端代码以在浏览器上提供回调函数,以处理查找Name
或Pic
的异步返回结果。直接返回和命令式编码风格是不可能的。
通常,您希望根据查询返回的信息更新用户屏幕上的内容。通常的Meteor编码是让回调函数用Session.set()
更新session global variable。模板可以引用这些会话变量,通过隐含或显式的Tracker.autorun(),可以在API返回数据时更新屏幕。
答案 1 :(得分:1)
你需要:
steamFunctions
移至仅在服务器上定义的methods。以下是基于原始问题的一些示例代码。请注意,这尚未经过测试,可能需要进行一些调整。
服务器/ methods.js 强>
const KEY = 'xxxxxxxxxxxxxxxx';
const URL = 'http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002';
Meteor.methods({
getName() {
const userSteamId = Meteor.user().profile.id;
const params = {
key: KEY,
steamids: userSteamId,
};
try {
var result = HTTP.get(URL, { params });
// Double check this - I have no idea what this API returns. The value
// you want may be nested under result, like result.data or something.
return JSON.parse(result).personaname;
} catch (e) {
// Something bad happened - maybe throw an error.
return false;
}
},
});
请注意,此方法是在服务器上定义的,因此我们不会将KEY
公开给客户端。另请注意,我们使用的是HTTP
api的同步版本,因此可以将值返回给客户端。
<强>的客户机/ LIB / user.js的强>
Tracker.autorun(function () {
user = Meteor.user();
if (user && user.profile && user.profile.id) {
Meteor.call('getName', (err, name) => {
Session.set('steamName', name);
});
} else {
Session.set('steamName', '');
}
});
当用户登录或更新时,获取蒸汽名称并设置全局会话变量。
<强>的客户机/模板/ profile.js 强>
Template.profile.helpers({
getName: function () {
return Session.get('steamName');
},
});
阅读steamName
会话变量,以便在模板中使用。