I set a cookie in web/js/site.js:
$.cookie("sidebar", "hidden", { path: '/' });
I read the cookie with PHP:
$sidebar_toggle_state = $_COOKIE['sidebar'];
Is it possible to use also the Yii Request Component to read such cookies? The following code doesn't read the cookie:
$sidebar_toggle_state = Yii::$app->request()->cookies()->getValue('sidebar', '');
See: http://www.yiiframework.com/doc-2.0/guide-runtime-sessions-cookies.html#cookies
When I set a new cookie through the Yii Response Component:
Yii::$app->response->cookies->add(new yii\web\Cookie([
'name' => 'sidebar',
'value' => 'hidden',
]));
Then the value of the cookie looks like this (because the cookie is protected):
3976220a3c8e46bb641aef1da3accfb1652bffd5bb9de503a9d6882e8a69f6f9a%3A2%3A%7Bi%3A0%3Bs%3A7%3A%22sidebar%22%3Bi%3A1%3Bs%3A6%3A%22hidden%22%3B%7D
Such cookie can the Yii Request Component read. But can it read also unprotected cookies?
Or, is it possible to set the Yii protected cookies with JavasSript / jQuery (without using AJAX)?
To read a cookie set by Javascript, you have, in configurations, config/web.php to set some request components properties to be false like the following:
'components' => [
'request' => [
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
'cookieValidationKey' => 'SomeRandomStringChars',
'enableCookieValidation' => false,
'enableCsrfValidation' => false,
],
This will allow reading cookies that have been set using Javascript like the following:
Yii::$app->getRequest()->getCookies()->getValue('theme');
Warning!
The above solution may has security issues, because we canceled the enableCookieValidation and enableCsrfValidation for all cookies. So there is another solution that allows jumping those validations for a specific cookie, suppose the theme cookie that we just have used in the example above, we will utilize the second parameter of getValue() method, i.e the default value, like the following:
Yii::$app->getRequest()->getCookies()->getValue('theme', (isset($_COOKIE['theme']))? $_COOKIE['theme']: 'theme')
The above solution will let you keeping both, enableCookieValidation and enableCsrfValidation to be true and only bypass them for a specific cookie.
Related
I'm trying to use the post method to pass the user to Laravel using a form in HTML so I can store the user in the UserController into the database. I get an CSRF Token mismatch error.
I have used this Method to store the user:
addUser(user: User):Observable<User>{
return this.http.post<User>(this.apiURL+'/addUser',user, httpOptions);
}
When I console.log the user it works fine. It shows me all attributes when I klick on submit.
I have use this Route in Laravel to store the user:
Route::post('/addUser','UserController#create');
In the Controllermethod I used this code:
public function create(Request $request)
{
$data2 = $request->json()->all();
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
Laravel, by default, has VerifyCsrfToken middleware enabled for all routes. This is for security (to avoid cross site attacks) and checks for a CSRF token for all requests. But you can set middlewares for route groups such as web, api',console`.
Try to move VerifyCsrfToken middleware from $middleware variable to web group in $middlewareGroups variable in Http/Kernel.php. By doing this, you only enable this middleware for web routes.
Hope this helps.
My slugs looks like this:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'<lang>/<p_page>/<p_category>/<p_product>' => 'splitter/manage-request',
'<lang>/<p_page>/<p_category>' => 'splitter/manage-request',
'<lang>/<p_page>' => 'splitter/manage-request',
'<lang>/' => 'splitter/manage-request',
'<lang>' => 'splitter/manage-request',
'' => 'splitter/manage-request',
],
],
I am sending all the requests to that SplitterController where I am parsing them. But I don't want the AJAXs to be send to it. Is it possible to give them some default route? To redirect them backend for example. I couldn't find information about it in the documentation? Appreciating links also is I missed it. Thank you!
According to my experience, there are probably the following options for your reference:
the first: The easiest way is to add a beforeAction() to your SplitterController, determine if it is an ajax request in beforeAction(), and redirect to your target address, for example:
public function beforeAction()
{
if (\Yii::$app->request->isAjax) {
return \Yii::$app->response->redirect($targetUrl);
}
return parent::beforeAction($action);
}
second: You can check if the request is an ajax request in the nginx configuration and then redirect to your target address
third: If you can't set up additional routing rules and configure the ajax request address, then you can consider implementing it by customizing UrlManager::parseRequest(), just check if it is an ajax request before it starts parsing the request, then redirect to your target. address
This answer is translated from Google Translate
I'm running some unit tests, one of the tests checks that emails are generated and sent.
I have checked the docs, to force Yii to save the emails to a file rather than send I have configured mailer component as follows:
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'viewPath' => '#common/mail',
// send all mails to a file by default. You have to set
// 'useFileTransport' to false and configure a transport
// for the mailer to send real emails.
'useFileTransport' => true
],
When running the tests I see the Yii::info message coming from the BaseMailer send() function.
[yii\mail\BaseMailer::send] 'Sending email "Direct Debit Payment Notification" to "test#test.co.uk"'
However the email doesn't get saved anywhere, should be runtime/mail, it is not sent anywhere either.
I have tried to set useFileTransport at runtime using:
$mailer = Yii::$app->mailer;
$mailer->useFileTransport = true;
$mailer->composer...
But nothing changes, any help is appreciated.
Codeception override your mailer settings ([1] [2]) to use custom mailer, which does not send or save anything. It makes sense - you don't want to send bunch of emails during testing.
You can use Codeception custom assertions or methods to test sent emails:
$I->seeEmailIsSent(3); // Test that three emails was sent
$messages = $I->grabSentEmails();
$I->assertEquals('admin#site,com', $messages[0]->getTo());
Looking at the Docs,yii\mail\BaseMailer::useFileTransport If enabled, this option enforces saving mail message data into the local files instead of regular sending. These files will be saved under yii\mail\BaseMailer::fileTransportPath, which is #runtime/mail by default.
So check your directory permissions if they are ok, you can change it to anyother directory that you know wont have permission issues by using fileTransportPath.
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'viewPath' => '#common/mail',
// send all mails to a file by default. You have to set
// 'useFileTransport' to false and configure a transport
// for the mailer to send real emails.
'useFileTransport' => true,
'fileTransportPath'=>'your/path',
],
A customer has requested to have the exact same endpoints available through web interface as well as through REST API.
The same endpoint should be visible using web browser only when being logged in. When accessing it via REST API, a valid access token must be submitted.
The rule for this specific endpoint is defined as follows:
[
'class' => 'yii\rest\UrlRule',
'controller' => 'site',
'pluralize' => false,
'extraPatterns' => [
'POST upload-raw-data' => 'uploadRawData'
],
]
Now, when I try to access this endpoint, I've got these results:
Browser: no problem
Postman / POST: 404 error
Postman / GET: no problem
When trying the same with enableStrictParsing enabled, I've got 404 errors all around.
If I need to provide other parts of the code, I'll happily provide them.
I think I found the solution for my issue. The problem seems to have been the CSRF validation.
By disabling it for this specific action in beforeAction(), the POST call behaves as intended.
public function beforeAction($action) {
if ($action->id == 'upload-raw-data')
Yii::$app->controller->enableCsrfValidation = false;
return parent::beforeAction($action);
}
source: https://gist.github.com/guerreiro/9e9cb3154b9047f5d2a0
Is it possible to run action of frontend controller from backend?
this code works if called action is in backend too. can i specify in runAction that controller/action is in frontend?
Yii::$app->runAction('controller/action')
Also i' m tried something like
$c=new controller();
$s->action();
too but it seems it not working too. //new controller() need some parameters and i have no idea what it is.
The yii\base\Application object has a public property controllerNamespace, which defaults to app\\controllers. You need to change it accordingly to changing default controller namespace.
Change namespace in action:
Yii::$app->controllerNamespace = 'frontend\controllers' and use runAction
A way could be this .
In your backend application config you could create an additional 'UrlManager' component
name eg: urlManagerFrontEnd
return [
'components' => [
'urlManager' => [
// here is your backend URL rules
],
'urlManagerFrontEnd' => [
'class' => 'yii\web\urlManager',
'baseUrl' => 'http://your_path/frontend/web/index.php',
'enablePrettyUrl' => true,
'showScriptName' => false,
],
],
];
Then you should invoke following to compose front-end URL:
Yii::$app->urlManagerFrontEnd->createUrl();
and add the controller/action you prefer
remeber that
runAction()
Runs an action within this controller with the specified action ID and
parameters.
http://www.yiiframework.com/doc-2.0/yii-base-controller.html#runAction()-detail
this mean that cannot run an action of another controller or of another application ..
If you need a service then you must configure a RESTFull or you simply need a redirection you can use redirect