mirror of
https://github.com/grocy/grocy.git
synced 2025-04-29 17:45:39 +00:00
Use session/cookie based authentication with login form instead of basic auth
This commit is contained in:
parent
bd3155d39b
commit
23146417e6
44
Grocy.php
44
Grocy.php
@ -101,4 +101,48 @@ class Grocy
|
|||||||
|
|
||||||
return self::$InstalledVersion;
|
return self::$InstalledVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static function IsValidSession($sessionKey)
|
||||||
|
{
|
||||||
|
if ($sessionKey === null || empty($sessionKey))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return file_exists(__DIR__ . "/data/sessions/$sessionKey.txt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function CreateSession()
|
||||||
|
{
|
||||||
|
if (!file_exists(__DIR__ . '/data/sessions'))
|
||||||
|
{
|
||||||
|
mkdir(__DIR__ . '/data/sessions');
|
||||||
|
}
|
||||||
|
|
||||||
|
$now = time();
|
||||||
|
foreach (new FilesystemIterator(__DIR__ . '/data/sessions') as $file)
|
||||||
|
{
|
||||||
|
if ($now - $file->getCTime() >= 2678400) //31 days
|
||||||
|
{
|
||||||
|
unlink(__DIR__ . '/data/sessions/' . $file->getFilename());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$newSessionKey = uniqid() . uniqid() . uniqid();
|
||||||
|
file_put_contents(__DIR__ . "/data/sessions/$newSessionKey.txt", '');
|
||||||
|
return $newSessionKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function RemoveSession($sessionKey)
|
||||||
|
{
|
||||||
|
unlink(__DIR__ . "/data/sessions/$sessionKey.txt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
"require": {
|
"require": {
|
||||||
"slim/slim": "^3.8",
|
"slim/slim": "^3.8",
|
||||||
"slim/php-view": "^2.2",
|
"slim/php-view": "^2.2",
|
||||||
"morris/lessql": "^0.3.4",
|
"morris/lessql": "^0.3.4"
|
||||||
"tuupola/slim-basic-auth": "^2.2"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
<Compile Include="GrocyDbMigrator.php" />
|
<Compile Include="GrocyDbMigrator.php" />
|
||||||
<Compile Include="index.php" />
|
<Compile Include="index.php" />
|
||||||
<Compile Include="views\consume.php" />
|
<Compile Include="views\consume.php" />
|
||||||
|
<Compile Include="views\login.php" />
|
||||||
<Compile Include="views\inventory.php" />
|
<Compile Include="views\inventory.php" />
|
||||||
<Compile Include="views\shoppinglistform.php" />
|
<Compile Include="views\shoppinglistform.php" />
|
||||||
<Compile Include="views\shoppinglist.php" />
|
<Compile Include="views\shoppinglist.php" />
|
||||||
@ -60,6 +61,7 @@
|
|||||||
<Content Include="views\consume.js" />
|
<Content Include="views\consume.js" />
|
||||||
<Content Include="views\dashboard.js" />
|
<Content Include="views\dashboard.js" />
|
||||||
<Content Include="views\inventory.js" />
|
<Content Include="views\inventory.js" />
|
||||||
|
<Content Include="views\login.js" />
|
||||||
<Content Include="views\shoppinglistform.js" />
|
<Content Include="views\shoppinglistform.js" />
|
||||||
<Content Include="views\shoppinglist.js" />
|
<Content Include="views\shoppinglist.js" />
|
||||||
<Content Include="views\purchase.js" />
|
<Content Include="views\purchase.js" />
|
||||||
|
64
index.php
64
index.php
@ -15,6 +15,7 @@ require_once __DIR__ . '/GrocyPhpHelper.php';
|
|||||||
$app = new \Slim\App(new \Slim\Container([
|
$app = new \Slim\App(new \Slim\Container([
|
||||||
'settings' => [
|
'settings' => [
|
||||||
'displayErrorDetails' => true,
|
'displayErrorDetails' => true,
|
||||||
|
'determineRouteBeforeAppMiddleware' => true
|
||||||
],
|
],
|
||||||
]));
|
]));
|
||||||
$container = $app->getContainer();
|
$container = $app->getContainer();
|
||||||
@ -22,18 +23,65 @@ $container['renderer'] = new PhpRenderer('./views');
|
|||||||
|
|
||||||
if (!Grocy::IsDemoInstallation())
|
if (!Grocy::IsDemoInstallation())
|
||||||
{
|
{
|
||||||
$isHttpsReverseProxied = !empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https';
|
$sessionMiddleware = function(Request $request, Response $response, callable $next)
|
||||||
$app->add(new \Slim\Middleware\HttpBasicAuthentication([
|
{
|
||||||
'realm' => 'grocy',
|
$route = $request->getAttribute('route');
|
||||||
'secure' => !$isHttpsReverseProxied,
|
$routeName = $route->getName();
|
||||||
'users' => [
|
|
||||||
HTTP_USER => HTTP_PASSWORD
|
if (!Grocy::IsValidSession($_COOKIE['grocy_session']) && $routeName !== 'login')
|
||||||
]
|
{
|
||||||
]));
|
$response = $response->withRedirect('/login');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$response = $next($request, $response);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
};
|
||||||
|
|
||||||
|
$app->add($sessionMiddleware);
|
||||||
}
|
}
|
||||||
|
|
||||||
$db = Grocy::GetDbConnection();
|
$db = Grocy::GetDbConnection();
|
||||||
|
|
||||||
|
$app->get('/login', function(Request $request, Response $response)
|
||||||
|
{
|
||||||
|
return $this->renderer->render($response, '/layout.php', [
|
||||||
|
'title' => 'Login',
|
||||||
|
'contentPage' => 'login.php'
|
||||||
|
]);
|
||||||
|
})->setName('login');
|
||||||
|
|
||||||
|
$app->post('/login', function(Request $request, Response $response)
|
||||||
|
{
|
||||||
|
$postParams = $request->getParsedBody();
|
||||||
|
if (isset($postParams['username']) && isset($postParams['password']))
|
||||||
|
{
|
||||||
|
if ($postParams['username'] === HTTP_USER && $postParams['password'] === HTTP_PASSWORD)
|
||||||
|
{
|
||||||
|
$sessionKey = Grocy::CreateSession();
|
||||||
|
setcookie('grocy_session', $sessionKey, time()+2592000); //30 days
|
||||||
|
|
||||||
|
return $response->withRedirect('/');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return $response->withRedirect('/login?invalid=true');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return $response->withRedirect('/login?invalid=true');
|
||||||
|
}
|
||||||
|
})->setName('login');
|
||||||
|
|
||||||
|
$app->get('/logout', function(Request $request, Response $response)
|
||||||
|
{
|
||||||
|
Grocy::RemoveSession($_COOKIE['grocy_session']);
|
||||||
|
return $response->withRedirect('/');
|
||||||
|
});
|
||||||
|
|
||||||
$app->get('/', function(Request $request, Response $response) use($db)
|
$app->get('/', function(Request $request, Response $response) use($db)
|
||||||
{
|
{
|
||||||
$db = Grocy::GetDbConnection(true); //For database schema migration
|
$db = Grocy::GetDbConnection(true); //For database schema migration
|
||||||
|
@ -1 +1 @@
|
|||||||
1.3.0
|
1.4.0
|
@ -38,6 +38,14 @@
|
|||||||
<a class="navbar-brand" href="/">grocy</a>
|
<a class="navbar-brand" href="/">grocy</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="navbar" class="navbar-collapse collapse">
|
||||||
|
<ul class="nav navbar-nav navbar-right">
|
||||||
|
<li>
|
||||||
|
<a class="discrete-link logout-button" href="/logout"><i class="fa fa-sign-out fa-fw"></i> Logout</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="navbar-mobile" class="navbar-collapse collapse">
|
<div id="navbar-mobile" class="navbar-collapse collapse">
|
||||||
|
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
@ -71,6 +79,12 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<ul class="nav navbar-nav navbar-right">
|
||||||
|
<li>
|
||||||
|
<a class="discrete-link logout-button" href="/logout"><i class="fa fa-sign-out fa-fw"></i> Logout</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
12
views/login.js
Normal file
12
views/login.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
$(function()
|
||||||
|
{
|
||||||
|
$('.logout-button').hide();
|
||||||
|
|
||||||
|
$('#username').focus();
|
||||||
|
|
||||||
|
if (Grocy.GetUriParam('invalid') === 'true')
|
||||||
|
{
|
||||||
|
$('#login-error').text('Invalid credentials, please try again.');
|
||||||
|
$('#login-error').show();
|
||||||
|
}
|
||||||
|
});
|
23
views/login.php
Normal file
23
views/login.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<div class="col-md-4 col-md-offset-5 main">
|
||||||
|
|
||||||
|
<h1 class="page-header text-center">Login</h1>
|
||||||
|
|
||||||
|
<form method="post" action="/login" id="login-form">
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="name">Username</label>
|
||||||
|
<input type="text" class="form-control" required id="username" name="username" />
|
||||||
|
<div class="help-block with-errors"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="name">Password</label>
|
||||||
|
<input type="password" class="form-control" required id="password" name="password" />
|
||||||
|
<div id="login-error" class="help-block with-errors"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button id="login-button" type="submit" class="btn btn-default">Login</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
Loading…
x
Reference in New Issue
Block a user