很长一段时间以来,我一直在为我的 API 使用 http digest auth,似乎它按我的预期工作。
但是,它似乎出现错误并提示重新验证三次。在第四个它只记录发送电子邮件的用户(作为用户名),即使密码错误
我对为什么在发送有效密码之前它不会继续重新验证感到有些困惑。
<?php
class Model_Authentication_Init {
const REALM = 'theaudienceauth';
protected $user_id = NULL;
protected $user_permissions = array();
protected $user;
protected $db;
public static $instance;
const ADMIN_PERMISSION_ID = 1;
public function __construct() {
$this->db = Zend_Registry::get('db');
}
public static function getInstance() {
if (!isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
protected function extractData() {
$realm = self::REALM;
if (empty ( $_SERVER ['PHP_AUTH_DIGEST'] )) {
header ( 'HTTP/1.1 401 Unauthorized' );
header ( 'WWW-Authenticate: Digest realm="' . $realm . '",qop="auth",nonce="' . uniqid () . '",opaque="' . md5 ( $realm ) . '"' );
exit ();
die ( 'Text to send if user hits Cancel button' );
}
//be careful username on account isnt the same as username in the db also, later
$data = http_digest_parse ( $_SERVER ['PHP_AUTH_DIGEST'] );
return $data;
}
protected function validateData($data, $password) {
$realm = self::REALM;
$A1 = md5 ( $data ['username'] . ':' . $realm . ':' . $password );
$A2 = md5 ( $_SERVER ['REQUEST_METHOD'] . ':' . $data ['uri'] );
$valid_response = md5 ( $A1 . ':' . $data ['nonce'] . ':' . $data ['nc'] . ':' . $data ['cnonce'] . ':' . $data ['qop'] . ':' . $A2 );
if ($data ['response'] != $valid_response) {
die ( 'Wrong Credentials!' );
}
}
public function authData($data) {
if (isset ($data ['username'])) {
$account_q = $this->db->query (" SELECT `id`, `encrypted_password` FROM `User` WHERE `email` = '".$data['username']."' AND `enabled` = 1 AND deleted = 0 ");
$account = $account_q->fetch ( PDO::FETCH_OBJ );
$account_q->closeCursor();
if (is_object ( $account )) {
$password_fetched = decrypt_password ( $account->encrypted_password ); //@todo might need to decr.
if (! defined ( 'CONNECTED_ACCOUNT_ID' )) {
define ( 'CONNECTED_ACCOUNT_ID', $account->id );
}
$_SESSION ['logged_in'] = 1;
$_SESSION ['CONNECTED_ACCOUNT_ID'] = $account->id;
$_SESSION ['email'] = $data['username'];
$user_permissions = Model_User_Permission::listing ( $account->id );
$_SESSION['user_permissions'] = $user_permissions;
$user_id = $account->id;
$account = NULL;
} else {
die ( 'Could not auth with details passed: email: ' . $data ['username'] );
}
}
$this->user_id = $user_id;
$this->user_permissions = $user_permissions;
return array($user_id, $user_permissions, $password_fetched);
}
/**
* Main auth method
* @throws Model_Exception_Application
*/
public function auth() {
$userId = NULL;
$user_permissions = NULL;
if (! isset ( $_SESSION ['logged_in'] ) || $_SESSION ['logged_in'] != 1) {
$data = $this->extractData();
list($userId, $user_permissions, $password_fetched) = $this->authData($data);
// analyze the PHP_AUTH_DIGEST variable
if (! ($data)) {
throw new Model_Exception_Application ( 903 );
die ( 'Wrong Credentials!' );
}
$this->validateData($data, $password_fetched);
} else {
if (! defined ( 'CONNECTED_ACCOUNT_ID' )) {
define ( 'CONNECTED_ACCOUNT_ID', $_SESSION ['CONNECTED_ACCOUNT_ID'] );
}
$userId = $_SESSION ['CONNECTED_ACCOUNT_ID'];
//if user permissions are not set to a session, set it
$user_permissions = $_SESSION['user_permissions'] = Model_User_Permission::listing($userId);// isset($_SESSION['user_permissions']) && !empty($_SESSION['user_permissions']) ? $_SESSION['user_permissions'] : Model_User_Permission::listing($userId);
}
$this->user_id = $userId;
$this->user = $_SESSION['user'] = Model_Baseclass::load_by_fields(array('table_name' => 'User', 'id' => $userId)); //isset($_SESSION['user']) && !empty($_SESSION['user']) ? $_SESSION['user'] : Model_Baseclass::load_by_fields(array('table_name' => 'User', 'id' => $userId));
$this->user_permissions = $user_permissions;
}
}
上面的调用是:
Model_Authentication_Init::getInstance($this->rest);
编辑:不确定现在的原因是什么,因为那是很久以前的事了,但我们开始吧:
<?php
class System_Authentication_Init {
const REALM = 'auth';
protected $user_permissions = array();
protected $user;
protected $db;
public static $instance;
const ADMIN_PERMISSION_ID = 1;
public function __construct() {
$this->db = Zend_Registry::get('db');
}
public static function getInstance() {
if (!isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
protected function extractData() {
$realm = self::REALM;
if (empty ( $_SERVER ['PHP_AUTH_DIGEST'] )) {
header ( 'HTTP/1.1 401 Unauthorized' );
header ( 'WWW-Authenticate: Digest realm="' . $realm . '",qop="auth",nonce="' . uniqid () . '",opaque="' . md5 ( $realm ) . '"' );
exit ();
die ( 'Text to send if user hits Cancel button' );
}
//be careful username on account isnt the same as username in the db also, later
$data = http_digest_parse ( $_SERVER ['PHP_AUTH_DIGEST'] );
return $data;
}
protected function validateData($data, $password) {
$realm = self::REALM;
$A1 = md5 ( $data ['username'] . ':' . $realm . ':' . $password );
$A2 = md5 ( $_SERVER ['REQUEST_METHOD'] . ':' . $data ['uri'] );
$valid_response = md5 ( $A1 . ':' . $data ['nonce'] . ':' . $data ['nc'] . ':' . $data ['cnonce'] . ':' . $data ['qop'] . ':' . $A2 );
if ($data ['response'] != $valid_response) {
session_destroy();
session_unset();
session_regenerate_id();
die ( 'Wrong Credentials!' );
}
}
public function authData($data) {
if (isset ($data ['username'])) {
$accountQuery = $this->db->query (" SELECT `id`, `encrypted_password` FROM `User` WHERE `email` = '".$data['username']."' AND `enabled` = 1 AND deleted = 0 ");
$account = $accountQuery->fetch ( PDO::FETCH_OBJ );
$accountQuery->closeCursor();
if (is_object ( $account )) {
$passwordReturned = decrypt_password ( $account->encrypted_password );
if (! defined ( 'CONNECTED_ACCOUNT_ID' )) {
define ('CONNECTED_ACCOUNT_ID', $account->id);
}
$_SESSION ['logged_in'] = 1;
$_SESSION ['CONNECTED_ACCOUNT_ID'] = $account->id;
$_SESSION ['email'] = $data['username'];
$user_permissions = Model_User_Permission::listing ( $account->id );
$_SESSION['user_permissions'] = $user_permissions;
$account = NULL;
} else {
die ( 'Could not auth with details passed: email: ' . $data ['username'] );
}
}
$this->user_permissions = $user_permissions;
return array($user_permissions, $passwordReturned);
}
/**
* Main auth method
* @throws System_Exception_Application
*/
public function authenticate() {
$user_permissions = NULL;
if (! isset ( $_SESSION ['logged_in'] ) || $_SESSION ['logged_in'] != 1) {
$data = $this->extractData();
list($user_permissions, $passwordReturned) = $this->authData($data);
// analyze the PHP_AUTH_DIGEST variable
if (! ($data)) {
throw new System_Exception_Application ( 903 );
die ( 'Wrong Credentials!' );
}
$this->validateData($data, $passwordReturned);
} else {
if (! defined ( 'CONNECTED_ACCOUNT_ID' )) {
define ( 'CONNECTED_ACCOUNT_ID', $_SESSION ['CONNECTED_ACCOUNT_ID'] );
}
//if user permissions are not set to a session, set it
$user_permissions = $_SESSION['user_permissions'] = Model_User_Permission::listing(CONNECTED_ACCOUNT_ID);// isset($_SESSION['user_permissions']) && !empty($_SESSION['user_permissions']) ? $_SESSION['user_permissions'] : Model_User_Permission::listing($userId);
}
$this->user = $_SESSION['user'] = Model_Baseclass::load_by_fields(array('table_name' => 'User', 'id' => CONNECTED_ACCOUNT_ID)); //isset($_SESSION['user']) && !empty($_SESSION['user']) ? $_SESSION['user'] : Model_Baseclass::load_by_fields(array('table_name' => 'User', 'id' => $userId));
$this->user_permissions = $user_permissions;
}
public function isAdmin() {
if (!$this->user_permissions || empty($this->user_permissions) ) {
$this->authenticate();
}
if ($this->user_permissions) {
foreach ($this->user_permissions as $user_permission) {
if (isset($user_permission->{'permission_id'}) && $user_permission->{'permission_id'} == self::ADMIN_PERMISSION_ID) {
return true;
}
}
}
return false;
}
/**
* returns user id
* @return User id
*/
public function getUserId() {
return $this->user->id;
}
/* Added by aaron
* returns the internal user object
* */
public function getUserObject() {
Zend_Registry::set('user', $this->user);
return $this->user;
}
/**
* returns user permissions
* @return _user_permissions User Permissions
*/
public function getUserPermissions() {
return $this->user_permissions;
}
}