mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 00:32:42 +01:00
CSRF / Logout
This commit is contained in:
parent
58d1506499
commit
29f7219a49
26 changed files with 152 additions and 7 deletions
|
@ -137,6 +137,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorFileViewController' => 'applications/files/controller/view',
|
||||
'PhabricatorLiskDAO' => 'applications/base/storage/lisk',
|
||||
'PhabricatorLoginController' => 'applications/auth/controlller/login',
|
||||
'PhabricatorLogoutController' => 'applications/auth/controlller/logout',
|
||||
'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/base',
|
||||
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/phpmailerlite',
|
||||
'PhabricatorMetaMTAController' => 'applications/metamta/controller/base',
|
||||
|
@ -290,6 +291,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorFileViewController' => 'PhabricatorFileController',
|
||||
'PhabricatorLiskDAO' => 'LiskDAO',
|
||||
'PhabricatorLoginController' => 'PhabricatorAuthController',
|
||||
'PhabricatorLogoutController' => 'PhabricatorAuthController',
|
||||
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter',
|
||||
'PhabricatorMetaMTAController' => 'PhabricatorController',
|
||||
'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO',
|
||||
|
|
|
@ -116,6 +116,7 @@ class AphrontDefaultApplicationConfiguration
|
|||
),
|
||||
|
||||
'/login/' => 'PhabricatorLoginController',
|
||||
'/logout/' => 'PhabricatorLogoutController',
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -86,7 +86,9 @@ class AphrontRequest {
|
|||
}
|
||||
|
||||
final public function isFormPost() {
|
||||
return $this->getExists(self::TYPE_FORM) && $this->isHTTPPost();
|
||||
return $this->getExists(self::TYPE_FORM) &&
|
||||
$this->isHTTPPost() &&
|
||||
$this->getUser()->validateCSRFToken($this->getStr('__csrf__'));
|
||||
}
|
||||
|
||||
final public function getCookie($name, $default = null) {
|
||||
|
|
|
@ -26,7 +26,7 @@ class PhabricatorLoginController extends PhabricatorAuthController {
|
|||
$request = $this->getRequest();
|
||||
|
||||
$error = false;
|
||||
$login_name = $request->getCookie('phu');
|
||||
$login_name = $request->getCookie('phusr');
|
||||
if ($request->isFormPost()) {
|
||||
$login_name = $request->getStr('login');
|
||||
|
||||
|
@ -89,6 +89,7 @@ class PhabricatorLoginController extends PhabricatorAuthController {
|
|||
|
||||
$form = new AphrontFormView();
|
||||
$form
|
||||
->setUser($request->getUser())
|
||||
->setAction('/login/')
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorLogoutController extends PhabricatorAuthController {
|
||||
|
||||
public function shouldRequireLogin() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$request->clearCookie('phsid');
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI('/login/');
|
||||
}
|
||||
|
||||
return id(new AphrontRedirectResponse())->setURI('/');
|
||||
}
|
||||
|
||||
}
|
15
src/applications/auth/controlller/logout/__init__.php
Normal file
15
src/applications/auth/controlller/logout/__init__.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||
phutil_require_module('phabricator', 'applications/auth/controlller/base');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorLogoutController.php');
|
|
@ -26,6 +26,9 @@ class PhabricatorConduitConsoleController
|
|||
}
|
||||
|
||||
public function processRequest() {
|
||||
|
||||
$request = $this->getRequest();
|
||||
|
||||
$methods = $this->getAllMethods();
|
||||
if (empty($methods[$this->method])) {
|
||||
$this->method = key($methods);
|
||||
|
@ -55,6 +58,7 @@ class PhabricatorConduitConsoleController
|
|||
|
||||
$form = new AphrontFormView();
|
||||
$form
|
||||
->setUser($request->getUser())
|
||||
->setAction('/api/'.$this->method)
|
||||
->appendChild(
|
||||
id(new AphrontFormStaticControl())
|
||||
|
|
|
@ -25,6 +25,8 @@ class DifferentialDiffViewController extends DifferentialController {
|
|||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
|
||||
$diff = id(new DifferentialDiff())->load($this->id);
|
||||
if (!$diff) {
|
||||
return new Aphront404Response();
|
||||
|
@ -40,6 +42,7 @@ class DifferentialDiffViewController extends DifferentialController {
|
|||
|
||||
$action_form = new AphrontFormView();
|
||||
$action_form
|
||||
->setUser($request->getUser())
|
||||
->setAction('/differential/revision/edit/')
|
||||
->addHiddenInput('diffID', $diff->getID())
|
||||
->addHiddenInput('viaDiffView', 1)
|
||||
|
|
|
@ -100,6 +100,7 @@ class DifferentialRevisionEditController extends DifferentialController {
|
|||
}
|
||||
|
||||
$form = new AphrontFormView();
|
||||
$form->setUser($request->getUser());
|
||||
if ($diff) {
|
||||
$form->addHiddenInput('diffID', $diff->getID());
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ class DifferentialRevisionViewController extends DifferentialController {
|
|||
$comment_form->setRevision($revision);
|
||||
$comment_form->setActions($this->getRevisionCommentActions($revision));
|
||||
$comment_form->setActionURI('/differential/comment/save/');
|
||||
$comment_form->setUser($request->getUser());
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
'<div class="differential-primary-pane">'.
|
||||
|
|
|
@ -21,6 +21,7 @@ final class DifferentialAddCommentView extends AphrontView {
|
|||
private $revision;
|
||||
private $actions;
|
||||
private $actionURI;
|
||||
private $user;
|
||||
|
||||
public function setRevision($revision) {
|
||||
$this->revision = $revision;
|
||||
|
@ -36,8 +37,11 @@ final class DifferentialAddCommentView extends AphrontView {
|
|||
$this->actionURI = $uri;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
public function setUser(PhabricatorUser $user) {
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$revision = $this->revision;
|
||||
|
||||
$actions = array();
|
||||
|
@ -47,6 +51,7 @@ final class DifferentialAddCommentView extends AphrontView {
|
|||
|
||||
$form = new AphrontFormView();
|
||||
$form
|
||||
->setUser($this->user)
|
||||
->setAction($this->actionURI)
|
||||
->addHiddenInput('revision_id', $revision->getID())
|
||||
->appendChild(
|
||||
|
|
|
@ -64,6 +64,7 @@ class PhabricatorDirectoryCategoryEditController
|
|||
}
|
||||
|
||||
$form = new AphrontFormView();
|
||||
$form->setUser($request->getUser());
|
||||
if ($category->getID()) {
|
||||
$form->setAction('/directory/category/edit/'.$category->getID().'/');
|
||||
} else {
|
||||
|
|
|
@ -73,6 +73,8 @@ class PhabricatorDirectoryItemEditController
|
|||
}
|
||||
|
||||
$form = new AphrontFormView();
|
||||
$form->setUser($request->getUser());
|
||||
|
||||
if ($item->getID()) {
|
||||
$form->setAction('/directory/item/edit/'.$item->getID().'/');
|
||||
} else {
|
||||
|
|
|
@ -34,6 +34,7 @@ class PhabricatorFileUploadController extends PhabricatorFileController {
|
|||
|
||||
$form = new AphrontFormView();
|
||||
$form->setAction('/file/upload/');
|
||||
$form->setUser($request->getUser());
|
||||
|
||||
$form
|
||||
->setEncType('multipart/form-data')
|
||||
|
|
|
@ -65,6 +65,7 @@ class PhabricatorMetaMTAMailingListEditController
|
|||
}
|
||||
|
||||
$form = new AphrontFormView();
|
||||
$form->setUser($request->getUser());
|
||||
if ($list->getID()) {
|
||||
$form->setAction('/mail/lists/edit/'.$list->getID().'/');
|
||||
} else {
|
||||
|
|
|
@ -49,6 +49,7 @@ class PhabricatorMetaMTASendController extends PhabricatorMetaMTAController {
|
|||
|
||||
|
||||
$form = new AphrontFormView();
|
||||
$form->setUser($request->getUser());
|
||||
$form->setAction('/mail/send/');
|
||||
$form
|
||||
->appendChild(
|
||||
|
|
|
@ -26,6 +26,8 @@ class PhabricatorMetaMTAViewController extends PhabricatorMetaMTAController {
|
|||
|
||||
public function processRequest() {
|
||||
|
||||
$request = $this->getRequest();
|
||||
|
||||
$mail = id(new PhabricatorMetaMTAMail())->load($this->id);
|
||||
if (!$mail) {
|
||||
return new Aphront404Response();
|
||||
|
@ -34,6 +36,7 @@ class PhabricatorMetaMTAViewController extends PhabricatorMetaMTAController {
|
|||
$status = PhabricatorMetaMTAMail::getReadableStatus($mail->getStatus());
|
||||
|
||||
$form = new AphrontFormView();
|
||||
$form->setUser($request->getUser());
|
||||
$form->setAction('/mail/send/');
|
||||
$form
|
||||
->appendChild(
|
||||
|
|
|
@ -84,6 +84,7 @@ class PhabricatorPeopleEditController extends PhabricatorPeopleController {
|
|||
}
|
||||
|
||||
$form = new AphrontFormView();
|
||||
$form->setUser($request->getUser());
|
||||
if ($user->getUsername()) {
|
||||
$form->setAction('/people/edit/'.$user->getUsername().'/');
|
||||
} else {
|
||||
|
|
|
@ -27,6 +27,8 @@ class PhabricatorUser extends PhabricatorUserDAO {
|
|||
protected $passwordSalt;
|
||||
protected $passwordHash;
|
||||
|
||||
private $sessionKey;
|
||||
|
||||
public function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_AUX_PHID => true,
|
||||
|
@ -60,4 +62,29 @@ class PhabricatorUser extends PhabricatorUserDAO {
|
|||
return $password;
|
||||
}
|
||||
|
||||
const CSRF_CYCLE_FREQUENCY = 3600;
|
||||
|
||||
public function getCSRFToken() {
|
||||
return $this->generateCSRFToken(time());
|
||||
}
|
||||
|
||||
public function validateCSRFToken($token) {
|
||||
for ($ii = -1; $ii <= 1; $ii++) {
|
||||
$time = time() + (self::CSRF_CYCLE_FREQUENCY * $ii);
|
||||
$valid = $this->generateCSRFToken($time);
|
||||
if ($token == $valid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function generateCSRFToken($epoch) {
|
||||
$time_block = floor($epoch / (60 * 60));
|
||||
// TODO: this should be a secret lolol
|
||||
$key = '0b7ec0592e0a2829d8b71df2fa269b2c6172eca3';
|
||||
$vec = $this->getPHID().$this->passwordHash.$key.$time_block;
|
||||
return substr(md5($vec), 0, 16);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ class PhabricatorPHIDAllocateController
|
|||
asort($options);
|
||||
|
||||
$form = new AphrontFormView();
|
||||
$form->setUser($request->getUser());
|
||||
$form->setAction('/phid/new/');
|
||||
|
||||
$form
|
||||
|
|
|
@ -14,6 +14,7 @@ phutil_require_module('phabricator', 'view/form/base');
|
|||
phutil_require_module('phabricator', 'view/form/control/submit');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ class PhabricatorPHIDLookupController
|
|||
}
|
||||
|
||||
$lookup_form = new AphrontFormView();
|
||||
$lookup_form->setUser($request->getUser());
|
||||
$lookup_form
|
||||
->setAction('/phid/')
|
||||
->appendChild(
|
||||
|
|
|
@ -73,6 +73,8 @@ class PhabricatorPHIDTypeEditController
|
|||
}
|
||||
|
||||
$form = new AphrontFormView();
|
||||
$form->setUser($request->getUser());
|
||||
|
||||
if ($type->getID()) {
|
||||
$form->setAction('/phid/type/edit/'.$type->getID().'/');
|
||||
} else {
|
||||
|
@ -85,6 +87,7 @@ class PhabricatorPHIDTypeEditController
|
|||
$type_immutable = false;
|
||||
}
|
||||
|
||||
|
||||
$form
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
|
|
|
@ -23,6 +23,12 @@ final class AphrontFormView extends AphrontView {
|
|||
private $header;
|
||||
private $data = array();
|
||||
private $encType;
|
||||
private $user;
|
||||
|
||||
public function setUser(PhabricatorUser $user) {
|
||||
$this->user = $user;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setAction($action) {
|
||||
$this->action = $action;
|
||||
|
@ -59,8 +65,13 @@ final class AphrontFormView extends AphrontView {
|
|||
}
|
||||
|
||||
private function renderDataInputs() {
|
||||
if (!$this->user) {
|
||||
throw new Exception('You must pass the user to AphrontFormView.');
|
||||
}
|
||||
|
||||
$data = $this->data + array(
|
||||
'__form__' => 1,
|
||||
'__csrf__' => $this->user->getCSRFToken(),
|
||||
);
|
||||
$inputs = array();
|
||||
foreach ($data as $key => $value) {
|
||||
|
|
|
@ -117,7 +117,26 @@ class PhabricatorStandardPageView extends AphrontPageView {
|
|||
if ($request) {
|
||||
$user = $request->getUser();
|
||||
if ($user->getPHID()) {
|
||||
$login_stuff = 'Logged in as '.phutil_escape_html($user->getUsername());
|
||||
$login_stuff =
|
||||
'Logged in as '.phutil_escape_html($user->getUsername()).
|
||||
' · '.
|
||||
'<form action="/logout/" method="post" style="display: inline;">'.
|
||||
phutil_render_tag(
|
||||
'input',
|
||||
array(
|
||||
'type' => 'hidden',
|
||||
'name' => '__csrf__',
|
||||
'value' => $user->getCSRFToken(),
|
||||
)).
|
||||
phutil_render_tag(
|
||||
'input',
|
||||
array(
|
||||
'type' => 'hidden',
|
||||
'name' => '__form__',
|
||||
'value' => true,
|
||||
)).
|
||||
'<button class="small grey">Logout</button>'.
|
||||
'</form>';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue