所以,最后我在Sails上构建的MMORTS游戏将转向Kongregate。有几个障碍,如连接websockets,但现在解决了。可能最后的障碍是保持经过身份验证的会话。我到处都在使用框架,我不知道认证会话是如何工作的。 主要问题可能是CSRF或CORS。 我正在使用Sails v1.0。所以,我从HTML开始,我上传到kongregate。我采用最简单的例子:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">
<script src="jquery.js"></script>
<script src='https://cdn1.kongregate.com/javascripts/kongregate_api.js'></script>
<script src="sails.io.js"
autoConnect="false"
environment="production"
headers='{ "x-csrf-token": "" }'
></script>
<script type="text/javascript">
io.sails.url = 'https://my-secret-game.com'; // or where you want
</script>
</head>
<script src="main.js"></script>
</html>
这是main.js,我也上传到kongregate
kongregateAPI.loadAPI(function(){
window.kongregate = kongregateAPI.getAPI();
var username = kongregate.services.getUsername();
var id = kongregate.services.getUserId();
var token = kongregate.services.getGameAuthToken();
$.get("https://my-secret-game.com/csrfToken", function (data, jwres) {
var params = {
username: username,
id: id,
token: token,
_csrf: data._csrf
};
$.post("https://my-secret-game.com/kong", params, function(data, jwr, xhr){
// cant set the cookie - because of chrome. this doesnt work
document.cookie = document.cookie + ';authenticated=true;sails.sid=' + data.id;
$.get("https://my-secret-game.com/csrfToken", function (data, jwres) {
var msg = {
testing_authentication: true,
_csrf: data._csrf
};
$.post("https://my-secret-game.com/test", msg, function(data, status){
// getting the 403 Forbidden, CSRF mismatch. trying to access
// the play/test route, which is protected by sessionAUTH
console.log('data.response', data.response)
});
});
});
});
});
问题是,每当我尝试使用sessionAUTH发布我的Sails后端时,我就会收到403 Forbidden。我也不能设置cookie - 可能是因为Chrome。我能做什么?当我获得CSRF令牌时,在下一个请求中,我的Sails应用程序会响应CSRF不匹配。它变得错了。
这是我的Sails后端服务器上的控制器
module.exports = {
kong: function (req, res, next) {
var url = 'https://api.kongregate.com/api/authenticate.json';
var kong_api_key = 'my-secred-api-key';
var params = req.allParams();
var request = require('request');
var req_form = {
"api_key": kong_api_key,
"user_id": params.id,
"game_auth_token": params.token
};
request({
url: url,
method: "POST",
json: true,
body: req_form,
timeout: 5000
}, function (err, response, body){
if(err) { console.log(err, 'ERR43'); return res.ok(); }
else {
if(!response.body.success) {
console.log('unsuccessful login from kongregate')
return res.ok();
}
// trying to use a existing user and authenticate to it
User.find({username: 'admin-user'}).exec(function(err, users) {
var user = users[0];
req.session.authenticated = true;
req.session.user = { id: user.id };
// trying to send session_id, so that i could hold it on kongregates cookies as `sid`
return res.send({ user: user, id: req.session.id });
});
}
});
},
有人可以帮助修复我的应用程序的身份验证和CSRF吗?
如果需要有关我的配置的更多信息,这是config / session.js
var prefixes = 'dev';
module.exports.session = {
secret: 'my-secret',
cookie: {
secure: false
},
adapter: 'redis',
host: 'localhost',
port: 6379,
ttl: 3000000,
db: 0,
prefix: prefixes + 'sess:',
};
配置/ policies.js
module.exports.policies = {
user: {
'new': 'flash',
'create': 'flash',
'edit': 'rightUser',
'update': 'rightUser',
'*': 'sessionAuth'
},
play: {
'*': 'sessionAuth'
}
};
API /政策/ sessionAuth.js
module.exports = function(req, res, next) {
if (req.session.authenticated) {
return next();
} else {
var requireLoginErr = [
{ name: 'requireLogin', message: 'You must be signed in' }
];
req.session.flash = {
err: requireLoginErr
};
res.redirect('/');
return;
}
};
配置/ security.js
module.exports.security = {
csrf: true,
cors: {
allowRequestMethods: 'GET,PUT,POST,OPTIONS,HEAD',
allowRequestHeaders: 'content-type,Access-Token',
allowResponseHeaders: '*',
allRoutes: true,
allowOrigins: '*',
allowCredentials: false,
},
};
哦,因为我没有答案(显然 - 这个问题很糟糕),回答我自己解决的解决方案 - 所以下次我能读懂自己。不确定它有多好,但至少它有效。
Sails CORS采用Express.js形式,如果我允许在配置中使用它,则允许将套接字连接到kongregate。但它不允许通过cookie发送sails.sid(身份验证令牌)以正常方式进行身份验证。
由于安全性,Chrome不允许使用javascript(我在Kongregate上没有后端)将Cookie设置为标头。因此,如果我无法发送带有标头的cookie,Sails就无法以正常方式验证请求。即使我允许CORS接受'cookie'标题 - 浏览器也不允许使用javascript设置cookie标头。
我可以创建一些像“身份验证”这样的唯一标头,并在那里设置sails.sid,扩展Sails的一些核心功能,以获取这个新的头而不是cookie头。但问题 - 在Sails支持我无法得到所有这个sails.sid并将其发送到我的外部前端..它在哪里创建?我怎样才能在Sails后端获得sails.sid?不确定 - 不能google它。
所以,我只是以最简单的方式进行身份验证 - 在帐户登录/注册时,我只是通过自己创建会话密钥 - 使用bcrypt哈希user_id + secret_token(取自sails配置密码)。并发送到前端{user_id:'abcd',secret_token:'a2dw412515 ...'}
我已经在Sails中使我的策略在每个POST / GET请求上进行身份验证 - 获取请求的session_id和user_id,并使用bcrypt进行比较,session_id是否与加密的user_id + secret_token相同。我希望它足够安全。
所以,它奏效了。我只需要禁用CSRF。也许有一天我会再次实现它,我只需要按照自己的方式编写它,而不是保留Sails的默认值。