我的PHP+JS+Ajax应用程序需要用户登录,然后将登录数据保存到$_SESSION。
有三种类型的用户:User、Moderator、Admin。每一个都比前一个拥有更多的权限。
所有查询都指向ajax_req.php
因为我想保持ajax_req.php的安全,我检查$_SESSION数据,以确定用户是否登录,他/她属于哪个组。
代码如下:
if(isset($_SESSION['logged'])) {
if(isset($_SESSION['group_id'])) {
$group_id=(int)$_SESSION['group_id'];
if($group_id==ADMIN_GROUP) {
$login_success=1;
} else if ($group_id==MODERATOR_GROUP) {
$login_success=1;
} else if ($group_id==USER_GROUP) {
$login_success=1;
} else {
$login_success=-1;
}
} else {
$login_success=-1;
}
}
if($login_success<1) {
header('HTTP/1.1 401 Unauthorized');
$ret = array('status' => 'FALSE', 'txt' => 'Unauthorized access. Please check if You are still logged in.' );
print json_encode($ret);
exit();
}
第一个问题:我这样做对吗?第二个问题
我想保护我的应用程序不发出意味着管理员的命令。
接下来,我有以下函数:
function assert_right($group_id, $needed) {
if($group_id==ADMIN_GROUP) {
return true;
} else if ($group_id==MODERATOR_GROUP) {
if($needed==USER_GROUP || $needed==MODERATOR_GROUP) {
return true;
}
} else if ($group_id==USER_GROUP) {
if($needed==USER_GROUP) {
return true;
}
}
header('HTTP/1.1 403 Forbidden');
$ret = array('status' => 'FALSE', 'txt' => 'Unauthorized access. You do not have sufficient rights to do this action.' );
print json_encode($ret);
exit();
}
在敏感动作之前我调用
assert_right($_SESSION['group_id'], ADMIN_GROUP);
第二个问题:第一种情况返回401,第二种情况返回403是否正确?基本上,403意味着"禁止",根据http://en.wikipedia.org/wiki/List_of_HTTP_status_codes的意思是"请求是合法的请求,但服务器拒绝响应它。"与401未授权响应不同,验证没有什么区别。"我还检查了https://dev.twitter.com/docs/error-codes-responses,这是另一个问题的答案。
对我来说,403似乎是正确的,因为如果用户已经登录,那么他/她可能没有admin帐户。更重要的是,除非我犯了编程错误或用户窃取了通过Ajax发送的数据,否则用户不应该看到这个。
还有一点需要注意:不会向用户显示401或403状态码:Ajax和JavaScript使用它们来显示适当的错误消息。如果收到401,JavaScript显示文本:"您似乎没有登录到服务器。"请打开新窗口并登录继续。登录后,点击这里检查连接。"如果收到403,则显示文本:"您似乎没有足够的权限来完成此操作。"
我是否正确使用了这些错误代码?
返回代码一点也不重要,因为它是AJAX请求,所以您可以返回任何您想要的东西。您返回错误代码,然后使用JS处理它,然后返回消息给用户。示例用户点击按钮删除,他/她可能没有权限这样做,所以你返回json: status: error, type: permission。然后向用户显示属于此错误类型的消息。
你应该把1和2结合起来。编写一个函数或类来检查它们的命令。例子:
$check = $session_check(USER_COMMAND);
if ($check) //has right
else //no right.
function session_check($command){
$userCmdList = array(COMMAND_1,2,3,4);
$modCmdList = array(COMMAND_2,3,4,5,6,7);
switch ($_SESSION['group_id']){
case "admin":
return true;
break;
case "mod":
if !in_array($command,$modCmdList) return false;
else return true;
break;
case "user":
if !in_array($command,$userCmdList) return false;
else return true;
break;
default:
break;
}
}
还记得为每个会话使用唯一的哈希,以防止会话hjhack
p/S:这是一个简单的回答,根据你目前的工作过程。