xss with laravel 5.1 - laravel-5

i am using laravel 5.1
i use this code to save posts to db
Auth::User()->posts()->save(Blog::create($request->all()));
and when i display post with this code some text and image i want to clean javascript and danger code !
<p>this is text</p>
<p> </p>
<p><img alt="" src="link" style="height:227px; width:342px" /></p>
<script>
alert("this is js");
</script>
{!! $post->content !!}
this is result
when i use
{{ $post->content }}
this is result
i want display images and prevent danger code any solutions

I don't know if it works on laravel 5.1 but on 5.0, you can use this :
<?php namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class XSSProtection
{
/**
* The following method loops through all request input and strips out all tags from
* the request. This to ensure that users are unable to set ANY HTML within the form
* submissions, but also cleans up input.
*
* #param Request $request
* #param callable $next
* #return mixed
*/
public function handle(Request $request, \Closure $next)
{
if (!in_array(strtolower($request->method()), ['put', 'post'])) {
return $next($request);
}
$input = $request->all();
array_walk_recursive($input, function(&$input) {
$input = strip_tags($input);
});
$request->merge($input);
return $next($request);
}
}
And add it in Kernel.php
protected $middleware = [
'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode',
'Illuminate\Cookie\Middleware\EncryptCookies',
'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
'Illuminate\Session\Middleware\StartSession',
'Illuminate\View\Middleware\ShareErrorsFromSession',
'App\Http\Middleware\VerifyCsrfToken',
'App\Http\Middleware\XSSProtection',
];
Thanks to kirkbushell : http://laravel-tricks.com/tricks/laravel-5-xss-middleware

Try {{{ }}} this will escape user input and you can use this to sensitize before store it in database so check these functions HTML::entities(); or e()

You are doing a wrong thing by allowing html code to go to our database.
That being said, make sure to sanitize input (make use of e($data['example'])) when saving content and output - by using {{ }} or {{{ }}}
As for the images, create a table that contains ONLY image name. Handle the rest by using your controller (image location and stuff).
Good idea is to create subdirectory named as ID of post and then to store image there.
For example post ID 7 will have dir -> images/7/imagename from database.

Related

Manage settings in an application

Mine is a self-taught question, I would like to better understand how to best deal with the settings of an application in Laravel.
Assuming you have a table "Settings":
option
value
site_name
Example_name
site_description
Example_description
How can I handle the update issue? And how can I take them?
If you want to use out-of-the-box Laravel you can create a model to assist you with that. In order for you to create a model, you can run php artisan make:model Setting or you can create a model manually. Below is an example which you should place in a new file (Setting.php) in the /App/Models directory.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Setting extends Model
{
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'Settings';
/**
* The primary key associated with the table.
*
* #var string
*/
protected $primaryKey = 'option';
/**
* Indicates if the model's ID is auto-incrementing.
*
* #var bool
*/
public $incrementing = false;
/**
* The data type of the auto-incrementing ID.
*
* #var string
*/
protected $keyType = 'string';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['option', 'value'];
}
You can then create a controller by running the following command: php artisan make:controller SettingController --resource --model=Setting. The command will automatically create a resource controller for the Setting model based on the Laravel documentation.
In your controller, you can request a certain value of one of your settings by using the following code:
// Retrieve a model by its primary key...
$site_name = Setting::find('site_name')->value;
Or you can request all settings listed in your database by using this line:
// Retrieve all settings
$settings = Setting::all();
You can further process the settings with code like this:
// Create a list of all options and associated values
foreach ($settings as $setting) {
echo $setting->option . ": " . $setting->value;
}
You can find way more information about Laravel models in the documentation and online.
I haven't tested the codes but they should work.
Update all options
If you want to update all options you should create a HTML form like this one:
<form action="{{ route('setting.update') }}" method="POST">
#csrf
#method('PUT')
#foreach ($settings as $setting)
<label>{{ $setting->option }}</label>
<input type="text" name="{{ $setting->option }}" value="{{ $setting->value }}"/>
#endforeach
<input type="submit">
</form>
In your update() function in your controller you can then update all values by using the following code:
public function update(Request $request)
{
$settings = Setting::update($request->all());
}
I'm not sure if the update will work correctly with the code above so please let me know :)
Spatie offer an open-source solution to managing laravel settings: https://github.com/spatie/laravel-settings I use a number of their other open-source solutions and they make life very easy.
Great material to learn from even if you decide not to use their package.

How to ensure a new route hits correct middleware in laravel

I have a laravel 5.5 app I am working on and it has an existing route which serves up html ready to be rendered to pdf:
Route::get('wkhtml/read/{documentId}/{pageId?}', $namespace . 'WkhtmlController#getRead')
->name('wkhtml.read')
->middleware('wkhtml');
This all works fine and when you navigate to the page, it shows the page ready to be rendered.
I want to make a differentiation between the pages shown here and pages which are going to be downloaded, so I added this route:
Route::get('wkhtml/download/{documentId}/{pageId?}', $namespace . 'WkhtmlController#getDownload')
->name('wkhtml.download')
->middleware('wkhtml');
If I navigate to the url eg app.localhost/wkhtml/download/123, instead of showing the pages, the user is being redirected to the login page. Nothing else has changed, so it is a bit confusing.
The WKHTMLFilter looks like this:
<?php
namespace App\Http\Middleware;
use Closure;
use App\Services\Document\Author;
use Illuminate\Http\Request;
class WKHTMLFilter
{
/**
* Handle an incoming request to one of the wkhtml routes
*
* #param Request $request
* #param Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
// If it's coming from the wkhtml
if (!Author::isWkhtml($request)) {
return response()->make('Not wkhtml, not allowed here', 403);
}
return $next($request);
}
}
The app/Http/Kernel.php has this:
protected $routeMiddleware = [
...
'wkhtml' => \App\Http\Middleware\WKHTMLFilter::class,
];
The request doesn't appear to be hitting App\Services\Document\Author#isWkhtml, as I placed a die-dump there:
public static function isWkhtml(Request $request)
{
dd('here');
At the moment though, the request is not even hitting this filter.
How can I get the request to use the filter/middleware, if not like above?
Thanks in advance.
So it turns out in Laravel there are exposed routes in the AuthenticatedSession middleware, I just needed to add my new route:
protected $publicRoutes = [
'wkhtml.read', // existing route
'wkhtml.download', // new route
...
];

Laravel 5.4 proper way to store Locale setLocale()

I need to know. What is the proper way to store Locale for user. If for each users' request I change the language by
App::setLocale($newLocale);
Would not it change language for my whole project and for other requests as well? I mean when one user changes language it will be used as default for other users.
Thanks in advance
If you set App::setLocale() in for example in your AppServiceProvider.php, it would change for all the users.
You could create a middleware for this. Something like:
<?php
namespace App\Http\Middleware;
use Closure;
class SetLocale
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
app()->setLocale($request->user()->getLocale());
return $next($request);
}
}
(You need to create a getLocale() method on the User model for this to work.)
And then in your Kernel.php create a middleware group for auth:
'auth' => [
\Illuminate\Auth\Middleware\Authenticate::class,
\App\Http\Middleware\SetLocale::class,
],
And remove the auth from the $routeMiddleware array (in your Kernel.php).
Now on every route that uses the auth middleware, you will set the Locale of your Laravel application for each user.
I solved this problem with a controller, middleware, and with session.
This worked for me well, hope it helps you.
Handle the user request via the controller:
Simply set the language to the users session.
/**
* Locale switcher
*
* #param Request $request
* #return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function switchLocale(Request $request)
{
if (!empty($request->userLocale)) {
Session::put('locale', $request->userLocale);
}
return redirect($request->header("referer"));
}
Route to switch locale:
Route::post('translations/switchLocale}', ['as' => 'translations.switch', 'uses' => 'Translation\TranslationController#switchLocale']);
Middleware to handle the required settings:
In the Middleware check the user's session for the language setting, if its pereset set it.
/**
* #param $request
* #param Closure $next
* #param null $guard
* #return mixed
*/
public function handle(Request $request, Closure $next, $guard = null)
{
if (Session::has('locale')) {
App::setLocale(Session::get('locale'));
}
}
Lastly the switching form:
{!! Form::open(["route" => "translations.switch", "id" => "sideBarLocaleSelectorForm"]) !!}
{!! Form::select("userLocale", $languages, Session::get("locale")) !!}
{!! Form::close() !!}
<script>
$(document).on("change", "select", function (e) {
e.preventDefault();
$(this).closest("form").submit();
})
</script>
When someone loads your website it uses the default which is set in the config file.
The default language for your application is stored in the config/app.php configuration file.
Using the App::setLocale() method would only change for a specific user which I assume would be set in the session, the config file value would not be altered.
You may also change the active language at runtime using the setLocale method on the App facade
You could see this in action yourself by opening your website in two different browsers (as they would be using two different sessions) then changing the locale in one and seeing the default load in the other.
https://laravel.com/docs/5.4/localization#introduction
You could create a middleware like below.
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class SetLocale
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
if (auth()->check() && $languageId = auth()->user()->language_id) {
$locale = Language::find($languageId)->locale;
app()->setLocale($locale);
}
if ($request->lang) {
app()->setLocale($request->lang);
}
return $next($request);
}
}
I was facing the same problem, the locale was changing in session but not in config. So have checked the session's locale in every blade and controller and set the default the language instant from there, here is the code on my blade file
#php
if(\Session::get('locale') == 'en')
\App::setLocale('en');
else
\App::setLocale('bn');
#endphp
Hope it will help you

Change language in Laravel 5

I just begin to use Laravel 5.4, In the login.blade.php i have
I don't like to put plain text in html code, is there a solution to make all the texts in seperate lang files to use them dynamically?
Thank you
The resources/lang folder contains localization files. The file name corresponds to the view that it will be used. In order to get a value from this file, you can simply use the following code:
`Lang::geConfig;
use Session;
class Locale
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
//$raw_locale = Session::get('locale');
$raw_locale = $request->session()->get('locale');
if (in_array($raw_locale, Config::get('app.locales'))) {
$locale = $raw_locale;
}
else $locale = Config::get('app.locale');
App::setLocale($locale);
return $next($request);
}
}
In app/Http/Kernel.php in $middlewareGroups=[ ... ] add the following line:
\App\Http\Middleware\Locale::class,
In routes/web.php add:
Route::get('setlocale/{locale}', function ($locale) {
if (in_array($locale, \Config::get('app.locales'))) {
session(['locale' => $locale]);
}
return redirect()->back();
});
Try this!
{{ #lang('messages.login') }}
Now Add login key with it's value under language file as below
return['login'=>'Login']; // write inside messages file
and Set your APP Config Local Variable Like 'en','nl','us'
App::setLocale(language name); like 'en','nl','us'
Laravel has a localization module.
Basically, you create a file, ex: resources/lang/en/login.php and put
return [
'header' => 'Login'
];
And in your template you use #lang('login.header') instead of Login.
You can have as many files in your /resources/lang/en directory and using #lang blade directive you put your file name (without extension) and desired value separated with dot.

How to get Larvel5.3 session data or Authentication data from public directory?

I wrote some php function in public directory because I have to use external library.
Then I can't retrieve any session data and authentication data from the controller I have tested with below php script
session_start();
var_dump($_SESSION['user']);
I have initial Session data from AdminMiddlware already
It awesome for using it in Resource->view directories but can not in public.
namespace App\Http\Middleware;
use App\User;
use Closure;
use Illuminate\Support\Facades\Auth;
class AdminMiddleware
{
/**
* Handle an incoming request. User must be logged in to do admin check
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = User::find(\Auth::user()->id);
if ((int) $user->is_admin == (int) config('auth.guards.is_admin')) {
$collection = collect(Auth::user());
$thisdata = $collection->toArray();
$request->session()->put('user', $thisdata);
return $next($request);
}
return redirect()->guest('/');
}}
Ok, the simplest way that I can see to get this to work with Laravel is:
(If you haven't done so already) Copy
public/gallery/scripts/filemanager.config.default.json
to
public/gallery/scripts/filemanager.config.json
Then set "fileConnector"(line 25) to "/authenticate-filemanager", e.g
"fileConnector": "/authenticate-filemanager",
This will tell your Filemanager application to load through the route /authenticate-filemanager.
Next, go to public/gallery/connectors/php/application/FmApplication.php and at the bottom change if(!auth()) to if(!auth()->check()) this will tell the application to use the built-in auth in Laravel.
Then you will need to set up the actual route (this is essentially the contents of filemanager.php without the auth() function):
Route::match(['GET', 'POST'], 'authenticate-filemanager', function () {
require_once(public_path('gallery/connectors/php/application/Fm.php'));
require_once(public_path('gallery/connectors/php/application/FmHelper.php'));
$config = [];
$fm = Fm::app()->getInstance($config);
$fm->handleRequest();
});
Because both GET and POST calls are made to the same endpoint match is used. Make sure you don't put this route behind the auth middleware.
Lastly, you just need to to go to app/Http/Middleware/VerifyCsrfToken.php and add 'authenticate-filemanager' to the $except array to disable csrf for the route.
Hope this helps!
Update for RichFilemanger ver. 2.7.6 and Laravel 5.6
I use RichFilemanager in HTML text editor in admin panel. So check for admin user is logged in.
in public/../RichFilemanager/config/filemanager.config.json
"connectorUrl": "/admin/authenticate-filemanager",
in route/web.php
Route::match(['GET', 'POST'], '/admin/authenticate-filemanager', function () {
//Here check is admin or user is authenticated. Can use: auth()->check()
$isAuth = \App\Libraries\Admin\AdminBLL::isAuth();
if(!$isAuth){
return 'Not authenticated';
}
return require_once(public_path('assets/plugins/RichFilemanager/connectors/php/filemanager.php'));
});
As was wrote before by Ross Wilson: Lastly, you just need to to go to app/Http/Middleware/VerifyCsrfToken.php and add 'admin/authenticate-filemanager' to the $except array to disable csrf for the route.
Last one - setup files folder location in public/../RichFilemanager/connectors/php/filemanager.php
$local->setRoot('userfiles/filemanager', true, true);

Resources