Возможна ли базовая / дайджест-проверка подлинности HTTP для каждого запроса в CakePHP 2.0? - PullRequest
4 голосов
/ 28 января 2012

В руководстве неясно, как это реализовать (предполагается, что вы уже знаете, что именно делаете, а в некоторых случаях чувствуете, как запоздалая мысль), и я честно почесал голову, пытаясь понять это из.

Проблема: аутентификация через HTTP-заголовки авторизации для всех запросов API

Насколько я смог протестировать, я могу использовать обычную аутентификацию и обычную регистрацию на основе форм в CakePHP, но только , сначала выполнив действие login, которое я определяю в аутентификации. составная часть. Это нормально, когда я захожу на сайт напрямую и работает как положено (за исключением дайджеста, который, похоже, совершенно ошибочен). Однако через cURL мне не повезло, если я уже не вошел в систему.

Очевидно, что для API это далеко не идеально. Я не хочу отправлять запрос на /login, прежде чем делать то, что я хочу, и я не могу ожидать, что пользователь войдет в систему вручную, поэтому у Cake есть файл cookie для чтения. Это должно быть без гражданства.

Любая попытка предоставить учетные данные для аутентификации вместе с каждым моим запросом (через cURL) игнорируется, и в ответ я получаю ошибку 403. Ни метод login, ни какой-либо из классов Auth не затрагиваются.

Что мне нужно сделать, чтобы Cake вел себя как настоящий API и позволял мне авторизоваться без сохранения состояния для каждого запроса? Мне придется свернуть свое решение?

1 Ответ

4 голосов
/ 02 апреля 2012

У меня есть централизованный API, который позволяет выполнять аутентификацию пользователей через HTTP-дайджест и требует от пользователей входа в систему для выполнения многих функций, связанных с пользователем. CakePHP принудительно выполняет вход в систему, проверяя, требует ли действие входа в систему, перенаправляя на ваше действие входа в систему (по умолчанию / users / login), затем вы можете перенаправить обратно.

Я создал свой API, выполнив следующее:

//Config/routes.php
///////////////////////////
/**
 * Users Controller routes for REST API 
 */
    Router::mapResources('users');
/**
 * Parses extensions for data serialization 
 */
    Router::parseExtensions();

//Controller/UserController.php
////////////////////////////////
<?php

App::uses('DigestAuthenticate', 'Controller/Component/Auth/');

class UsersController extends AppController {

    var $name = 'Users';

    //Login callback
    function login() {
        //dont render for login, just a call back for auth
        $this->autoRender = false;

        if ($this->Auth->login()) {
            $this->redirect($this->Auth->redirect());
        }
    }

    //GET /users.[xml|json]
    //this is the basic call that tests user authentication
    //basically a login then echo
    function index() {
        if ($this->Auth->login()) {
            $user = $this->Auth->user();

            $this->User->id = $user['id'];
            $this->User->saveField('last_login', date('Y-m-d H:i:s'));

            $this->set('response', array(
                'response' => array(
                    'code' => 'users_auth_success',
                    'message' => 'User has passed authentication',
                    'data' => $user
                )
            ));
            //will serialize to xml or json based on extension
            $this->set('_serialize', 'response');
        } 
    }
}

?>

Затем вы можете использовать этот API-интерфейс примерно так:

$c = curl_init($uri . '.' . $this->_format);

curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_USERPWD, $login['user'] . ':' . $login['pass']);
curl_setopt($c, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, true);

$response = curl_exec($c);
$info = curl_getinfo($c);

curl_close($c);

if($info['http_code'] == $this->_http_codes['OK']) {
    //success
    if($this->_format == 'xml')
        $response = Xml::toArray(Xml::build($response));
    else//JSON
        $response = json_decode($response);
        return $response['response']['data'];
} else if($info['http_code'] == $this->_http_codes['Unauthorized']) {
    return false;
} else {
    return null;
}
...