开发者

Correct HTML status codes for unauthorized access and forbidden access. (using Ajax)

My PHP+JS+Ajax application requires users to log in, then saves login data to $_SESSION.

There are three types of users: User, Moderator, Admin. Each has more rights than previous.

All queries are made to ajax_req.php

Because I want to keep the ajax_req.php secure, I check the $_SESSION data to determine if the user is logged in and in what group He/She belongs.

The code for this is following:

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();
}

First question: Am I doing this right?

Second question

I want to protect my application from issuing commands meant for admins.

Next, I have following function:

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();
}

And before sensitive action I call

assert_right($_SESSION['group_id'], ADMIN_GROUP);

Second question: Is it correct to return 401 in the first case and 403 on the second? Basically, 403 means "Forbidden", which according to http://en.wikipedia.org/wiki/List_of_HTTP_status_codes means "The request was a legal request, but the server is refusing to respond to it. Unlike a 401 Unauthorized response, authenticating will make no difference.". I also checked https://dev.twitter.com/docs/error-codes-responses, which was given as answer to another question.

For me, 403 seems correct, because if user is already logged in, then He/She probably does not have admin account. What's more, user should never see this unless I have made programming error or user hacks data sent through Ajax.

One more thing to notice: user is not shown the 401 or 403 status codes: they are used by Ajax and JavaScript to show appropriate error messages. If 401 is received, JavaScript shows text: "It seems that You are not logged in to server. Please open up new window and log in to continue. After You have logged in, click here to check connection.". If 403 is received, text is shown: "It seems that You do not have sufficient rights to 开发者_JS百科complete this operation.".

Am I using those error codes correctly?


Your return code is not important at all, because it's AJAX request so you are able to return anything you want. You return error code then process it using JS then return message to user. Example user click on button delete, he/she may do not have permission to do this, so you return json: status: error, type: permission. Then display to user the message belong to this error type.

You should combine 1 and 2 together. Write a function or class to check their command. Example:

$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;
    }
}

Also remember to use a unique hash for each session to prevent session hjhack

P/S: This is simple answer that follow your current work process. Other improved methods are always available.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜