boi*_*dil 5 cakephp basic-authentication cakephp-2.3
我尝试了位于http://book.cakephp.org/2.0/en/tutorials-and-examples/simple-acl-controlled-application/simple-acl-controlled-application的"Simple Acl受控应用程序1和2"教程. HTML.
执行此操作后,我尝试激活BasicAuth而不是FormAuth.
我在我的UsersController中重新实现了login()函数,如下所示:
public function login() {
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirect());
} else {
$this->Session->setFlash('Not able to login');
}
}
Run Code Online (Sandbox Code Playgroud)
并将我的AppController中的$ components变量更改为以下内容:
public $components = array(
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
),
'authenticate' => array('Basic')
),
'DebugKit.Toolbar',
'Session'
);
Run Code Online (Sandbox Code Playgroud)
BasicAuth"弹出窗口"按预期显示,但是当我尝试登录时,它会在无限循环中重新启动.除了包含DebugKit之外,我在完成教程后没有做任何改动.
我错过了什么?我希望有人可以帮助我,因为我想在下一个项目中使用CakePHP编码!
更新
AppController的
public function beforeFilter() {
//Configure AuthComponent
$this->Auth->allow('display');
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'posts', 'action' => 'add');
}
Run Code Online (Sandbox Code Playgroud)
UsersController
public function beforeFilter() {
parent::beforeFilter();
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试/users/使用本教程中描述的FormAuth 访问例如哪个像魅力一样,因此不存在权限问题.Logindata非常简单,可以测试(admin:admin),所以也没有问题.
更新2
在我的Apache Log中,我得到以下内容,因此它说我没有被授权:
IP - - [16/Apr/2013:18:08:37 +0200]"GET/users/login HTTP/1.0"401 5179" - ""Mozilla/5.0(Windows NT 6.2; Win64; x64; rv:23.0) Gecko/20130414 Firefox/23.0"
更新3
由于某些原因,似乎用户和密码未发送或未保存在PHP中.如果我重写/lif/Cake/Controller/Auth/BasicAuthenticate以下内容,它会起作用!
public function authenticate(CakeRequest $request, CakeResponse $response) {
$_SERVER['PHP_AUTH_USER'] = $_SERVER['PHP_AUTH_PW'] = "admin";
$result = $this->getUser($request);
if (empty($result)) {
$response->header($this->loginHeaders());
$response->statusCode(401);
$response->send();
return false;
}
return $result;
}
Run Code Online (Sandbox Code Playgroud)
更新4
不知道那有用,但是服务器正在运行Plesk 11,最新更新,没有特别的修改.
更新5
好吧,"thaJeztah"的答案很有用,但现在我遇到了更多可以细分的问题.
将模式从fcgid更改为apache模块
1.1.工作登录的结果,但注销不起作用!重定向后,会话似乎被清除,但我仍然可以访问每个受限制的页面,直到我清除我的浏览器"Active Logins",因为它在Firefox中调用.
Run Code Online (Sandbox Code Playgroud)var_dump($this->Session->read('Auth.User')); NULL
当我访问/ users/login时,我会自动登录并重定向,而无需输入登录凭据.
Run Code Online (Sandbox Code Playgroud)print "<pre>"; print_r($this->Session->read('Auth.User')); print "</pre>"; Array ( [id] => 1 [username] => admin [group_id] => 1 [created] => 2013-04-12 12:54:26 [modified] => 2013-04-16 14:27:24 [is_active] => 1 [Group] => Array ( [id] => 1 [name] => Admin [created] => 2013-04-12 12:46:42 [modified] => 2013-04-12 12:46:42 ) )
使用基于.htaccess的解决方案也可以工作,它甚至看起来好像那是唯一需要的更改(我删除了list()代码,因为我从来没有进入它并且它也可以工作).
2.1.与上面相同的问题,没有真正的注销可能.
更新6
可能是我最后一次或最后一次更新.:-)现在我正在尝试通过将用户作为我创建的访客用户登录进行"虚假注销",该用户只能访问/users/login和/pages/home:http://guest:guest@my.domain/users/login
访问/users/logout也可能有用,因为我在那里使用这段代码:
public function logout() {
$user = $this->User->find('first', array('conditions' => array('username' => 'guest')));
$this->Auth->login($user['User']['id']);
}
Run Code Online (Sandbox Code Playgroud)
我不相信,这将是一致的,因为我相信会话数据将被删除一段时间,浏览器仍然得到主动管理员登录并使用这些进行身份验证 - 我是对的吗?
之后我可以再次使用登录其他用户http://admin:admin@my.domain/users/login.不完美,但至少适用于Firefox.
基本上最后一个问题:关于如何在访问时强制使用BasicAuth的任何建议/users/login?这样我就可以随时使用任何客户端轻松切换用户.
更新7
在我接受的答案中,我找到了一种方法来完成这个想法.我希望我抓住了所有边缘案例,如果没有,请随时纠正我!
(Ps:当使用ACL和/或基本身份验证时,至少AppController中的isAuthorized()似乎被忽略(它被识别,但没有效果 - 当我删除方法而不更改$ components时,我得到了一个错误)我不使用isAuthorized()来实现它.)
AppController.php
public function beforeFilter($redirectlogin = true) {
//Configure AuthComponent
$this->Auth->allow('display', '/users/login');
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->logoutRedirect = array('controller' => 'pages', 'action' => 'home');
$this->Auth->loginRedirect = array('controller' => 'pages', 'action' => 'home');
$this->Auth->unauthorizedRedirect = array('controller' => 'HTTPCODE', 'action' => 'c403');
if($redirectlogin && $this->Session->read('Auth.needs_reauthenticate')) {
if(!($this->request->params['controller'] == $this->Auth->loginRedirect['controller'] && $this->request->params['pass'][0] == $this->Auth->loginRedirect['action'])) {
$this->redirect('/users/login');
}
}
}
Run Code Online (Sandbox Code Playgroud)
UsersController.php
public function beforeFilter() {
parent::beforeFilter(false);
}
public function login() {
$this->autoRender = false;
$this->Session->write('Auth.needs_reauthenticate', true);
if(!$this->Session->check('Auth.count')) {
$count = 1;
} else {
$count = $this->Session->read('Auth.count') + 1;
}
$this->Session->write('Auth.count', $count);
if($this->Session->read('Auth.needs_reauthenticate')) {
if((isset($_SERVER['HTTP_AUTHORIZATION']) && $this->Session->read('Auth.count') == 1) || (!isset($_SERVER['HTTP_AUTHORIZATION']) || empty($_SERVER['HTTP_AUTHORIZATION']) || !$this->Session->check('Auth.sent_header_step') || $this->Session->read('Auth.sent_header_step') < 1)) {
unset($_SERVER['HTTP_AUTHORIZATION']);
$this->Session->write('Auth.redirectTo', $this->Auth->redirect());
$this->response->header(sprintf('WWW-Authenticate: Basic realm="%s"', env('SERVER_NAME')));
$this->response->statusCode(401);
$this->response->send();
$this->Session->write('Auth.sent_header_step', 1);
}
if(isset($_SERVER['HTTP_AUTHORIZATION'])) {
$this->Session->write('Auth.sent_header_step', 0);
$base64string = base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6));
if(!(strlen($base64string) > 1 && substr($base64string, -1, 1) != ":")) {
$_SERVER['PHP_AUTH_USER'] = "";
$_SERVER['PHP_AUTH_PW'] = "";
}
$data = true;
}
$this->Auth->logout();
if(isset($data) && $this->Session->read('Auth.count') > 1) {
if($this->Auth->login()) {
$this->Session->write('Auth.needs_reauthenticate', false);
if($this->Session->check('Auth.redirectTo')) {
$redirectTo = $this->Session->read('Auth.redirectTo');
$this->Session->delete('Auth.redirectTo');
$this->Session->delete('Auth.count');
return $this->redirect($redirectTo);
} else {
return $this->redirect($this->Auth->redirect());
}
} else {
$this->response->statusCode(403);
// my 403 message
}
} else {
if(!isset($_SERVER['HTTP_AUTHORIZATION']) && $this->Session->read('Auth.count') > 1 && isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW']) && trim($_SERVER['PHP_AUTH_USER']) != "" && trim($_SERVER['PHP_AUTH_PW']) != "") {
if($this->Auth->login()) {
$this->Session->write('Auth.needs_reauthenticate', false);
if($this->Session->check('Auth.redirectTo')) {
$redirectTo = $this->Session->read('Auth.redirectTo');
$this->Session->delete('Auth.redirectTo');
$this->Session->delete('Auth.count');
unset($_SERVER['HTTP_AUTHORIZATION']);
unset($_SERVER['PHP_AUTH_USER']);
unset($_SERVER['PHP_AUTH_PW']);
return $this->redirect($redirectTo);
} else {
return $this->redirect($this->Auth->redirect());
}
} else {
$this->response->statusCode(403);
// my 403 message
}
}
$this->response->statusCode(403);
// my 403 message
}
}
}
Run Code Online (Sandbox Code Playgroud)
提前致谢
阿德里安
您的网站可能配置为以(快速)CGI 方式运行 PHP,在这种情况下,变量中不存在PHP_AUTH_USER和键。BasicAuthenticate AuthComponent 依赖于这些密钥。PHP_AUTH_PWD$_SERVER
更改 Plesk 中的域/虚拟主机设置以将 php 作为该网站/域的“apache 模块”运行,或者扩展 BasicAuthenticate 组件以其他方式获取这些变量。
有关此主题的更多信息可以在这个问题中找到:
对于 Symfony 框架,似乎有人编写了一种解决方法,在这种情况下也可能有用;
https://github.com/symfony/symfony/issues/1813
使用时注销basic authentication实际上是不可能的。基本身份验证是一种“无状态”身份验证机制,这基本上意味着浏览器在每次请求时都会发送用户凭据。换句话说; 服务器不保留“状态”,而浏览器则保留。使用基本身份验证,您需要浏览器发送用户凭据,并且只要浏览器发送有效凭据,您就允许浏览器访问受保护的页面。
注销的唯一方法是关闭浏览器,或告诉浏览器关闭活动会话/登录。
在这里阅读更多信息:
http://en.wikipedia.org/wiki/Basic_access_authentication
基本身份验证不是一种安全身份验证机制;每次请求时,用户名和密码都会发送到服务器。密码未加密发送(仅进行 Base64 编码以防止特殊字符出现问题)。
虽然表单身份验证也发送未加密的密码,但它(更)安全,因为它只会在登录时发送用户名/密码。后续请求只会发送 Session-id,该 Session-id 可以设置为过期并限制为特定的 IP 和/或浏览器类型。
在所有情况下,通过 SSL 保护连接显然很重要。
这只是“大声思考”,未经测试且高度实验性:)
尝试这个;
如果没有活动会话,请按照正常方式进行。在基本身份验证中无法区分“已登录”用户和“新用户” - 它是无状态的
如果会话处于活动状态,则用户显然正在进行活动会话。不要破坏会话,而是改变规则;
$this->Auth->user('username');用户(或者更好: ?,则使会话无效(而不是destroy)并通过发送登录标头强制用户重新进行身份验证;此外,检查会话内部是否仍然“有效” AppController::isAuthorized()(请参阅使用 ControllerAuthorize)
像这样的东西(样机代码):
登录页面/操作:
if ("usercredentials sent by browser" === "current logged in user in session") {
// Mark session as 'needs-to-reauthenticate'
$this->Session->write('Auth.needs_reauthenticate', true);
// Need to find a clean approach to get the BasicAuth loginHeaders()
// *including* the right settings (realm)
$this->response->header(/*BasicAuth::loginHeaders()*/);
// Access denied status
$this->response->statusCode(401);
return $this->response->send();
}
Run Code Online (Sandbox Code Playgroud)
AppController::isAuthorized()
if ($this->Session->read('Auth.needs_reauthenticate')) {
return false;
} else {
// Normal 'isAuthorized()' checks here
}
Run Code Online (Sandbox Code Playgroud)
注意:一旦浏览器在活动会话期间访问了“登录”页面,用户将必须使用不同的凭据登录,或者关闭浏览器以再次登录。
如果关闭并重新打开浏览器后会话 cookie 仍然存在,这可能会出现问题。尝试强制会话 cookie 成为“真正的”会话 cookie,并通过设置在浏览器关闭时将其删除Session.cookieTimeout(0请参阅Session Configuration
| 归档时间: |
|
| 查看次数: |
4853 次 |
| 最近记录: |