I'm trying to change checkIfUserIsAdmin() method in CheckIfAdmin middleware for disabling access to all users without role admin
What happened:
Nothing. backpack_user()->can(...) or backpack_user()->role(...) don't working...
Is that right way to restrict user access to admin panel?
bp - 3.5
laravel - 5.7
php - 7.2
First, create a middleware:
php artisan make:middleware AdminMiddleware
In this file we will check that the user has ‘admin’ role
<?php
namespace App\Http\Middleware;
use Closure;
class AdminMiddleware
{
public function handle($request, Closure $next)
{
if (! \Auth::user()->hasRole('admin'))
return response(trans('backpack::base.unauthorized'),401);
return $next($request);
}
}
Now, add this middleware to /config/backpack/base.php
(don’t delete CheckIfAdmin middleware, just append it)
'middleware_class' => [
\Backpack\Base\app\Http\Middleware\CheckIfAdmin::class,
\App\Http\Middleware\AdminMiddleware::class
],
Offcourse we must cache the config then
php artisan config:cache
One way is to make a Middleware in Http\Middleware like CheckIfAdmin.php with below function.
private function checkIfUserIsAdmin($user)
{
return ($user->is_admin == 1);
}
Then add this middleware in array $routeMiddleware of Http\Kernel.php. Like below.
'admin' => \App\Http\Middleware\checkIfUserIsAdmin::class,
Related
I have a question regarding symfony/form using as a standalone component and security-csrf running with PHP build-in server. I hardly remember having such issue with the Symfony framework.
When setting symfony/form as a standalone component I tried this code for both v4.2 and v5.1 https://github.com/xmgcoyi/standalone-forms/tree/4.2+twig. A rewrite of webmozart's example mentioned here https://symfony.com/doc/current/components/form.html
The csrf token is generated with twig-bridge, but when submitting the form - on calling$form->isValid() - invalid csrf error appears.
By default csrf protection is enabled, setting to false - the form submits.
Tried CSRF component with both setups with NativeSessionTokenStorage and SessionTokenStorage + Session of HttpFoundation.
Could you give any hint on what I'm doing wrong and where to look at?
P.S.
Code samples with csrf error on submission:
https://github.com/xmgcoyi/standalone-forms/tree/4.2+twig
https://github.com/liorchamla/pratique-symfony-form/tree/06-protection-csrf
UPD
The apps above work well, the problem was in browser storage filled with garbage.
Setting to false in $formFactory->createBuilder(FormType::class, null, ['csrf_protection' => false]) submits the form
This is a bit of a guess but the 4.2 linked repo has:
$csrfManager = new CsrfTokenManager($csrfGenerator, $csrfStorage);
$csrfTokenManager = new CsrfTokenManager();
Two token managers. One is used in the twig form engine and one is used in the form factory extension. Does not seem like a reasonable thing to do.
Here is an updated 5.1 working example. I stripped it down even more from your linked repo. But the only thing that I really changed was the token manager.
# index.php
require_once '../vendor/autoload.php';
$app = new App();
$app->run();
final class App
{
public function run()
{
$csrfGenerator = new UriSafeTokenGenerator();
$csrfStorage = new NativeSessionTokenStorage();
$csrfManager = new CsrfTokenManager($csrfGenerator, $csrfStorage);
$twig = new Environment(new FilesystemLoader([
'../templates',
'../vendor/symfony/twig-bridge/Resources/views/Form',
]));
$formEngine = new TwigRendererEngine(['form_div_layout.html.twig'], $twig);
$twig->addRuntimeLoader(new FactoryRuntimeLoader([
FormRenderer::class => function () use ($formEngine,$csrfManager) {
return new FormRenderer($formEngine, $csrfManager);
},
]));
$twig->addExtension(new TranslationExtension());
$twig->addExtension(new FormExtension());
$formFactory = Forms::createFormFactoryBuilder()
->addExtension(new CsrfExtension($csrfManager))
//->addExtension(new ValidatorExtension($validator))
->getFormFactory();
$form = $formFactory->createBuilder()
->add('firstName', TextType::class)
->getForm();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$form->submit($_POST[$form->getName()]); // form
if ($form->isValid()) {
dump('form is valid');
}
}
echo $twig->render('index.html.twig', [
'form' => $form->createView(),
]);
}
}
The composer.json is simply:
{
"require": {
"symfony/form": "^5.1",
"symfony/twig-bridge": "^5.1",
"symfony/translation": "^5.1",
"symfony/security-csrf": "^5.1"
},
"require-dev": {
"symfony/var-dumper": "^5.1"
}
}
If you still have trouble then I would suggest tracking down where the sessions are stored and then verifying the that csrf token is being properly stored. It should look something like:
_csrf|a:1:{s:4:"form";s:43:"9v1tUNe3J3eYVOmEPwVdz5_iISfzBg8Qa9pLMV8tSN4";}
This was actually kind of an interesting exercise in using the twig system for standalone forms. Thanks.
I want to show a signup form on a website but then when user hits submit, the form data will be posted to a Laravel app (on a different server) for registration.
So far, laravel stops it throwing the CSRF not found exception. Any idea how to work around it ?
If both applications are yours?
You can create a new middleware group:
protected $middlewareGroups = [
'web' => [
...
],
'remote-login' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
// \App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
Commenting/removing/disabling the VerifyCsrfToken middleware. Then map it to a new file:
protected function mapWebRoutes()
{
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
Route::middleware('remote-login')
->namespace($this->namespace)
->group(base_path('routes/remote-login.php'));
}
Then in your routes/remote-login.php, you better create a non-trivial login route:
Route::group(['prefix' => 'remote-login'], function () {
Route::get('/auth/8g7h6jk5l4oA/', function () {
dd('do you authentication');
});
});
Antonio's approach will work, but it's easier to just add the routes you don't want protected by the CSRF middleware to the $except array in app/Http/Middleware/VerifyCsrfToken.php.
I'm struggling with the Laravel's locale on Fresh new Project. I googled many times, but they didn't solve my problem.
Then I followed locale in laravel 5.4 returns to the pervious locale after refresh source, but it works only when I call pages by view
return view('home');
And it does not work when I use routes
return redirect()->route('home');
Here are my files:
web.php
Route::get('/lang/{locale}', function ($locale) {
App::setLocale($locale);
Session::put('locale', $locale);
//return view('home'); ###### This one works
return redirect()->route('home'); ###### Where as this does NOT work
});
Route::get('/', function () {
return view('welcome');
});
Route::get('/home', 'HomeController#index')->name('home');
home.blade.php
<div class="panel-body">
You are logged in!
{{__('auth.success')}}
<br>
Rus
<br>
Kgz
</div>
ChangeLocale.php Middleware (I call it for every request of pages)
public function handle($request, Closure $next)
{
if(Session::has('locale')) {
app()->setLocale(Session::get('locale'));
}
return $next($request);
}
Thanks in advance ;)
Ok, after I changed
Route::get('/home', 'HomeController#index')->name('home');
to
Route::get('/home', 'HomeController#index')->name('home')->middleware('changeLocale');
It started to work.
So, why my Middleware, is not working?
Should I assign middleware seperately to all my routes?
You may add your changeLocale middleware to web group in app/Http/Kernel.php:
protected $middlewareGroups = [
'web' => [
...
\Your\ChangeLocateMiddleware::class
],
...
]
As you may see in app/Providers/RouteServiceProvider.php, this middleware group applies to all your web routes.
It seems that Laravel 5 by default applies the CSRF filter to all non-get requests. This is OK for a form POST, but might be a problem to an API that POSTs DELETEs etc.
Simple Question:
How can I set a POST route with no CSRF protection?
Go to app/Http/Middleware/VerifyCsrfToken.php and then enter your routes(for which you want to disable csrf token) in the $except array.
for example:
class VerifyCsrfToken extends BaseVerifier
{
protected $except = [
'/register'
];
}
You can exclude URIs from CSRF by simply adding them to the $except property of the VerifyCsrfToken middleware (app/Http/Middleware/VerifyCsrfToken.php):
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
class VerifyCsrfToken extends BaseVerifier
{
/**
* The URIs that should be excluded from CSRF verification.
*
* #var array
*/
protected $except = [
'api/*',
];
}
Documentation: http://laravel.com/docs/5.1/routing#csrf-protection
My hack to the problem:
CSRF is now a "middleware" registered globally in App\Http\Kernel.php. Removing it will default to no CSRF protection (Laravel4 behavior).
To enable it in a route:
Create a short-hand key in your app/Providers/RouteServiceProvider.php :
protected $middleware = [
// ....
'csrf' => 'Illuminate\Foundation\Http\Middleware\VerifyCsrfToken',
];
You can now enable it to any Route:
$router->post('url', ['middleware' => 'csrf', function() {
...
}]);
Not the most elegant solution IMO...
just listen to this. Just before 30 minute i was facing this same problem. Now it solved. just try this.
Goto App -> HTTP-> Kernel
open the kernel file.
there you can see : \App\Http\Middleware\VerifyCsrfToken::class,
just disable this particular code using //
Thatz it! This will work!
So that you can remove the middleware from the API calling (if you want so..)
I'm trying to implement a login system that will be smart enough to redirect a user back to the page they were on before they decided (or were forced to) go to the login page.
I know this seems like a similar question to this one, and this one, but they do not address both of my scenarios.
There are two scenarios here:
User specifically decides to go to login page:
<a href="<?php echo $this->url(array(
'controller'=>'auth',
'action'=>'login'), 'default', true); ?>">Log In</a>
User is redirected because they tried to access protected content:
if (!Zend_Auth::getInstance()->hasIdentity()) {
$this->_helper->redirector('login', 'auth');
}
How can I implement a solution for this without displaying the "redirect to" url in the address bar?
Save the destination URL in the session. I guess you have some kind of access pre-dispatch plug-in. Do it there. And then, in the login form handler, check for the destination URL in the session, and redirect to it after a successful authentication.
Sample code from my project:
class Your_Application_Plugin_Access extends Zend_Controller_Plugin_Abstract {
public function preDispatch(Zend_Controller_Request_Abstract $request) {
foreach (self::current_roles() as $role) {
if (
Zend_Registry::get('bootstrap')->siteacl->is_allowed(
$role,
new Site_Action_UriPath($request->getPathInfo())
)
) return; // Allowed
}
$this->not_allowed($request);
}
private function not_allowed(Zend_Controller_Request_Abstract $request) {
$destination_url = $request->getPathInfo();
// If the user is authenticted, but the page is denied for his role, show 403
// else,
// save $destination_url to session
// redirect to login page, with $destination_url saved:
$request
->setPathInfo('/login')
->setModuleName('default')
->setControllerName('login')
->setActionName('index')
->setDispatched(false);
}
...
}
Here, current_roles() always contains 'guest', which is unauthenticated user, for which Zend_Auth::hasIdentity() is false.