ZF2: Define URL http or https - php

Here is my problem.
I have a few pages in my application who uses SSL, like the lggin page. When i am in the main page (who doens't have SSL), every link created by the view ( href=$this->url(...) ) is plain html, even the login page. On the other hand, when i am in the login page, every other links displays with https.
In the controller, i manipulate if the page uses SSL or not, that is OK. But i want to show the correct link for the user when he navigates through the site, https for ssl pages and http for non-ssl ones.
Thanks.

First of all, if you have HTTPS available, you should use it on any page. It is really against the web of trust when you have some pages available via HTTPS, but others not. Sure, you might enforce HTTPS on some pages (so there is no HTTP), but vice versa is always a bad idea.
That being said, you can create a scheme route. With the scheme you are able to specify HTTPS on some routes:
'secure' => [
'type' => 'scheme',
'options' => [
'scheme' => 'https',
'defaults' => [
// the usual stuff
],
],
'may_terminate' => false,
'child_routes' => [
// all your https routes here
],
],
Because some of these "secure" routes might be defined at vendor level (e.g. you use ZfcUser), you can use "prototyping" of routes. For example all ZfcUser routes should only be accessible via HTTPS. The "main" route of ZfcUser is zfcuser:
'router' => [
'prototypes' => [
// Define "secure" prototype to add to routes
'secure' => [
'type' => 'scheme',
'options' => ['scheme': 'https'],
],
],
// Apply the scheme route to ZfcUser
'routes' => [
'zfcuser' => [
'chain_routes' => ['secure'],
],
],
],
Prototyping "prepends" the secure route to zfcuser. So this makes zfcuser and all its childs a child-route of secure. Therefore, all zfcuser routes are defined with HTTPS.
When you've come this far: if you now assemble the routes, they will get HTTPS automatically. When you have a route login inside the secure route of my first example, you get the url via $this->url('secure/login');.
In the second case (prototyping) you don't need to mention the prototype, just use $this->url('zfcuser'); for the user's route.

Related

Yii2 urlmanager rules for pretty urls fails

I have the following url manager path
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'<controller:(\w|-)+>/' => 'site/index',
'<module:api\w+>/<controller:\w+>/<action:(\w|-)+>' => '<module>/<controller>/<action>',
],
]
What am looking for is all urls not rendered via api module paths to run via site/index but all other paths having api/* to be executed via module paths.
The above works for urls like /login, /auth but when i run urls like
/administrative/uom
It fails
SO basically i want all urls to be redirrected via site/index but all urls having api as the prefix like api/auth/login to be run via their respective controllers.
I have added an api module which should handle this.
What else do i need to add to make this work?
When adding rules always start from more detailed to less detailed. And you added general rule for controller only so no URL with action is matched. Do this
'rules' => [
'api/<controller:\w+>/<action:[\w\-]+>' => 'api/<controller>/<action>',
'<controller:[\w\-]+>/<action:[\w\-]+>' => 'site/index',
'<controller:[\w\-]+>/' => 'site/index',
],

Separate authentication for front-end user and admin in cakephp 3.x

We are working on a project where are 4 roles. But in cakephp 3.x Auth component holds authenticate user data in session with Auth.User indexing using
$this->Auth->setUser($user);
Due to this we are not able to access front-end user account from admin panel for some purpose, because of when we login to front-end user from admin panel, front-end login action performs and over write of session value.
So if there is any process to handle this please suggest us.
Thank you in advance.
As well I have understood that you are not using prefix to manage back-end and front-end user then may be you worked with separate folder structure for back-end, May I right?
You are right that $this->Auth->setUser($user); always holds session with Auth.User indexing. So you need to write different session indexing for back-end, and you can do it as follow :
For back-end user authentication :
**
$this->loadComponent('Auth', [
'authorize' => ['Controller'], // Added this line
'loginRedirect' => [
'controller' => 'Users',
'action' => 'dashboard',
'prefix' => 'admin_panel'
],
'logoutRedirect' => [
'controller' => 'Users',
'action' => 'login',
'prefix' => 'admin_panel'
],
'storage' => [
'className' => 'Session',
'key' => 'Auth.Admin',
]
]);
**
Here you can pass your desired index in 'storage' array key value.
I think it'll works for you.
Check out the section Authentication and Authorization in this curated list of CakePHP Plugins.
You could, for example, use dereuromarks TinyAuth Plugin to authorize your users and configure what they are able to see.
This way you can use the same authentication (be aware of the differences between Authentication and Authorization) and the same users table, which will prevent the Session conflict you mentioned.
The Auth component overwrite the previous session because it store the session in Auth.users all the time so we have to change the session key for different role.
If you are using URL prefix for the different roles to access then you can do like this.
AppController.php
public function beforeFilter(Event $event)
{
if($this->request->params['prefix']){
$this->Auth->config('storage', [
'key'=>'Auth.'.$this->request->params['prefix'],
'className'=>'Session'
]);
}
return parent::beforeFilter($event); // TODO: Change the autogenerated stub
}
This will create different roles in Auth as you required.
The session will be like this
[
'Auth'=>[
'User'=>['id'=>''],
'Admin'=>['id'=>''],
]
]
Tested it, working great for me.

Yii 2 canonical URL in urlManager configuration

I've got urlManager section in app configuration with several URLs per route:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
'rules' => [
'article-a' => 'article/a', // canonic comes first
'article-deprecated-a' => 'article/a',
'article-another-a-is-deprecated' => 'article/a',
'b-annoucement' => 'announcement/b', // canonic comes first
'legacy-b-annoncement' => 'announcement/b',
...
SEF URLs for routes are stored in frontend/config/main.php as an array, with multiple URLs per route. The first URL for the given route (i.e. /article-a) is canonical and the rest are legacy URLs.
What's the most natural way to specify canonical URL for a group of URLs that are pointing to the same route? It can be either rel="canonical" in view or 301/302 redirect to canonical URL.
Canonical URLs should be preferably specified in a place where the routes were defined (frontend/config/main.php configuration file in this case). The requirement here is that canonical URL should be defined outside of the controller, not hard-coded to controller.
I'm not sure how exactly you need to manage your rules so I'll go for a general use case and I'll base my answer on what I did understand from Paddy Moogan's Article which I will resume within the following example and I hope it helps on designing your required solution:
requirement:
Assuming a Search Engine did send a robot to check page B in my website and I'm not fine with people getting to page B instead of page A. So this is how I can clarify my point to the robot:
Forcing a 301 redirect to page A:
Telling the Search Engine that this page is permanently moved to page A. So please don't send more people to it. Send them to page A instead.
Forcing a 302 redirect to page A:
Telling the Search Engine that this page is temporary moved to page A. So do whatever you think it
is appropriate.
Opening page B (200 status code) but insert a Canonical
link element
pointing to page A:
Telling the Search Engine that this page is working fine but it is to me a secondary page and I would suggest sending the next visitors to page
A instead.
design:
So based on that this is how I would see a possible structure to my rules configuration:
'rules' => [
[
// by default: 'class' => 'yii\web\UrlRule',
'pattern' => '/',
'route' => 'site/index',
],
[
// the custom class
'class' => 'app\components\SEOUrlRule',
'pattern' => 'about',
'route' => 'site/about',
'permanents' => [
'deprecated-about',
'an-older-deprecated-about'
],
'temporaries' => [
'under-construction-about',
],
'secondaries' => [
'about-page-2'
]
],
[
// different route with own action but canonical should be injected
'class' => 'app\components\SEOUrlRule',
'pattern' => 'experimental-about',
'route' => 'whatever/experimental',
'canonical' => 'about'
],
]
This way I can chain as much arrays as I need to use Yii's default class yii\web\UrlRule while I can have a custom one in my app components folder dedicated to SEO related controllers.
Before going to code, this is how I would expect my website to behave :
You visit the /about page you get a 200 response (no
canonical added).
You visit the /deprecated-about page you get redirected to
/about with 301 status code.
You visit the /under-construction-about page you get redirected to
/about with 302 status code.
You visit the /about-page-2 page you get a 200 response (rendered by index/about action). No redirections except a similar tag to this is automatically injected into source code:
<link href="http://my-website/about" rel="canonical">
You visit the /experimental-about page you get a 200 response (rendered by its own action whatever/experimental) but with that same canonical tag above injected.
code:
The SEOUrlRule will simply extend \yii\web\UrlRule and override its parseRequest method to define the extra attributes based on which we will force a HTTP redirection or call parent::parseRequest() after registering the canonical link tag to the Yii::$app->view:
namespace app\components;
use Yii;
class SEOUrlRule extends \yii\web\UrlRule
{
public $permanents = [];
public $temporaries = [];
public $secondaries = [];
public $canonical = null;
public function parseRequest($manager, $request)
{
$pathInfo = $request->getPathInfo();
if(in_array($pathInfo, $this->permanents))
{
$request->setPathInfo($this->name);
Yii::$app->response->redirect($this->name, 301);
}
else if(in_array($pathInfo, $this->temporaries))
{
$request->setPathInfo($this->name);
Yii::$app->response->redirect($this->name, 302);
}
else if($this->canonical or in_array($pathInfo, $this->secondaries))
{
$route = $this->name;
if ($this->canonical === null) $request->setPathInfo($route);
else $route = $this->canonical;
Yii::$app->view->registerLinkTag([
'rel' => 'canonical',
'href' => Yii::$app->urlManager->createAbsoluteUrl($route)
]);
}
return parent::parseRequest($manager, $request);
}
}
And that is all what it needs. Note that Yii::$app->controller or its related actions won't be yet available at this early stage of solving routes as it is shown in this lifecycle diagram but it seems that Yii::$app->view is already initialized and you can use its $params property to set custom parameters (as it is done in this example) which may be useful for more advenced cases where more data should be shared or populated to final output.
I think you will have problems when creating the URL from the application to "article/a".
Why not use htaccess or the vhost file to do a 302 redirect to the proper URL?
If you want to handle it through the urlManager, I think you can just register the canonical link
$this->registerLinkTag(['rel' => 'canonical', 'href' => 'article/a']);
in the view.
Mode details here: http://www.yiiframework.com/doc-2.0/yii-helpers-baseurl.html#canonical()-detail
Yii2 provides a tool to generate canonnical urls based on your rules.
\helpers\Url::canonical()
The idea is that it will provide you an url to 'article-a'.

Simultaneous authorization in advanced app

In advanced app, I tried to implement divided authorization for backend and frontend.
In first case, I used User class from basic app, in order to use users without database. But for frontend part, I used User class from advanced app.
It would seemthat everything is working perfectly. But when you try to log in at the same time on both sides, the latter takes precedence over the previous one. Ie after entering the frontend parts - automatically eject the user from the backend and vice versa.
You have to set different cookies for frontend and backend in config/main.php file. For Eg.:
In backend:
'components' => [
'session' => [
'name' => 'BACKENDID', //Set name
'savePath' => __DIR__ . '/../tmp', //create tmp folder and set path
],
],
In Frontend:
'components' => [
'session' => [
'name' => 'FRONTENDID',
'savePath' => __DIR__ . '/../tmp',
],
],

What is 'may_terminate' in zend framework 2?

I am beginner working with Zend. I have seen may_terminate in module route configuration. I don't understand what it is for. According to ZF2 official docs,
the option “may_terminate” hints to the router that no other
segments will follow it.
Still I don't get the meaning of no other segments will follow it. What is it here? Can anyone please explain it with small example?
The may_terminate option will indicate to the router that 'this' route is able to be matched solely on the value of its route; even when it defines child_routes.
Consider the following example route configuration.
'router' => [
'routes' => [
'home' => [
'type' => 'literal',
'options' => [
'route' => '/home',
],
'may_terminate' => false,
'child_routes' => [
'foo' => [
'type' => 'literal',
'options' => [
'route' => '/foo',
],
],
],
],
],
],
There is some ambiguity in the above configuration, which only occurs with routes that define children. Do we want to allow our users to match on two routes or just one?
We could allow matching on just the /home part; which would mean we have two routes both
/home and /home/foo or we might only want to allow /home/foo.
This is where the may_terminate option is used. If we browsed to /home in our browser, when the routing occurs the router cannot regard the home route as a matchable route as may_terminate = false. In ZF2 terminology the router cannot "terminate" at this route and continues on searching for a match into the child_routes, which will fail and a 404 error will be raised.
So by modifying the value of the may_terminate option in the above example, we can change the routes that can be matched on.
may_terminate = true
home
home/foo
may_terminate = false
home/foo

Categories