I cannot figure out how to use another Cache service for storing my nonces using the WsseAuthentication. The documentation is unclear to me. Can anybody help me setup my nonce cache for use with Redis?
Currently, I know how to add a new nonce cache service id, like this:
firewalls:
#...
wsse_secured:
#...
wsse:
#...
nonce_cache_service_id: cache_nonces
and I know how to create this service id:
services:
cache_nonces:
class: Doctrine\Common\Cache\RedisCache
arguments: ???
But I don't know what arguments to give. When I use RedisCache, it expects a Redis object, and I dont know where to get this object and add this to arguments.
Just remove "arguments:", the class Doctrine\Common\Cache\RedisCache https://github.com/doctrine/cache/blob/master/lib/Doctrine/Common/Cache/RedisCache.php doesn't have a constructor, so you should not pass any variables with "arguments"
Related
Is there a way to check if the header of the request has a key value, compare with another value stored in the env and then give or not the access?
Note: I want to do it inside the firewall in security.yml.
Something like the "guard-authentication" from the docs but I don't need all those methods (getCredentials, getUser, etc... )
I think you are looking for a kernel controller filter, then you can parse the header of the request and search for the required parameter. For the env var you can set it as a parameter as below
//services.yaml
parameters:
your_variable: '%env(YOUR_ENV_VARIABLE)%'
then call it from service container
$var = $container->getParameter('your_variable');
and finally you can use a voter in your controller action to allow/deny access
I have a service that needs to access the current application base URL (what's returned by app.request.getBaseURL() in Twig views). Currently, my config is like this:
services:
WidgetModel:
class: AppBundle\Model\WidgetModel
scope: prototype
arguments: ['%widgets%']
So as a second argument, I would like to inject the base URL. Is it possible? If not, what would be proper solution?
As far as I know there is no builtin base url service. Which is actually a bit of a red flag that maybe having your component depending on it might not be such a good idea. But I can't think of a good reason why.
So normally, one would just inject the request object. But that has it's own problems as documented here: http://symfony.com/blog/new-in-symfony-2-4-the-request-stack
Instead, inject the #request_stack service and pull the url from it:
class WidgetModel
{
public __construct($widgets,$requestStack)
{
$this->baseUrl = $requestStack->getCurrentRequest()->getBaseUrl();
If you do find yourself needing the baseUrl in multiple services then you could define your own factory type service to generate it. But again, that might mean your design needs rethinking.
You can use the expression language in your service definition.
This example should do what you want:
services:
WidgetModel:
class: AppBundle\Model\WidgetModel
scope: prototype
arguments: [%widgets%, "#=service('request').getBaseUrl()"]
It fetches the request service and then executes the getBaseUrl method.
You will need to add a second parameter in your WigetModel for the base URL.
To complete the answer, in Symfony 3 you can use request_stack to get the base url using expressions languages (updated link) such as:
services:
WidgetModel:
class: AppBundle\Model\WidgetModel
scope: prototype
arguments: [%widgets%,"#=service('request_stack').getCurrentRequest().getBaseUrl()"
I'm trying to use the method described on this other question and I wasn't able to make it work:
Symfony2: How to inject ALL parameters in a service?
In summary, I would like to define the arguments of my service in a unique file using a variable. I would then only pass this variable as an argument to my service. If one day, I decide to change the arguments, I don't have to change all the calls on my service. I would just change the content of this variable. However, I'm having the following error:
Symfony\Component\DependencyInjection\Exception\InvalidArgumentException You cannot dump a container with parameters that contain references to other services (reference to service "doctrine.orm.entity_manager" found in "/company.usermanagerservice/em").
Was anybody able to make it work? Or do you have other ideas?
Edit:
services.yml:
company.user_manager:
class: Company\CoreBundle\Model\UserManager
arguments: [%company.userManagerService%]
Then on config.yml:
parameters:
company.userManagerService:
em: 'doctrine.orm.entity_manager'
user_helper: 'company.helper.user'
fos_manipulator: 'fos_user.util.user_manipulator'
I got a problem to add custom logic to some Symfony classes.
SwitchUserListener
I want to add a check, that a user cannot switch to a another user, which have more rights/roles, than the initial user.
First attempt
Overwrite the parameter in the security_listeners.xml with the key:
security.authentication.switchuser_listener.class But where can I overwrite it?
In the security.yml it didn't work:
security:
...
authentication:
switchuser_listener:
class: Symfony\Component\Security\Http\Firewall\SwitchUserListener
Second attempt
Overwrite the service for the SwitchUserListner service id: security.authentication.switchuser_listener
I create the same service in my service.xml of my bundle, but my class was not used / called.
Another idea was to overwrite only the class, but that only works for bundles, but the SwitchUserListener was not in the SecurityBundle, it was in the symfony component directory and that seemed to me as a really bad idea to overwrite the SecurityBundle
Third attempt
Now I get the solution: First time I didn't realize that the dispatcher call listener for the SWTICH_USER event in the SwitchUserListener:
$switchEvent = new SwitchUserEvent($request, $token->getUser());
$this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent);
So I need only to create a service with the special tag for this event type:
<tag name="kernel.event_listener" event="security.switch_user" method="onSecuritySwitchUser" />
And do the check in the given method.
This seems to be a better solution thatn the other two. But there is still a problem. In my listener for the SwitchUserEvent I need to ignore my custom check if the user wants to exit the switched user.
So I need to check the requested path: ignore if path containts '?switch_user=_exit'
But the path (URL parameter) can be changed:
# app/config/security.yml
security:
firewalls:
main:
# ...
switch_user: { role: ROLE_ADMIN, parameter: _want_to_be_this_user }
But in my bundle I can't read this parameter, because it will not be passed to the service container. It will be passed to the constructor of the SwitchUserListner class and will be saved there as private attribute, never accessable (without Reflection) from outside. (that happens here: SecurityExtension.php line 591) So what to do? Define the parameter twice go against DRY. Use Reflection?
And the other point is that there aren' every time events that will be fired on which I write a subscriber class. So what would be another / best solution for it?
I ask this question because I will get some similar problem where I want to add or overwrite something of the symfony intern components.
TemplateGuesser
I wanted to modify the TemplateGuesser: For a specific bundle all Templates which has the annotation #Tempalte the tempate file should be located with the controller TestController#showAction at this path:
Resources/views/customDir/Test/show.html.twig
So the guesser should be put and locate everything into a additional folder customDir instead of using only views. When using the render function with a specific template, the guesser should ignore the annotation.
I created my own Guesser and overwrite the service id: sensio_framework_extra.view.guesser and in comparision to the SwitchUserListener this time my class is really called instead of the original guesser. Why it works here but not with the SwitchUserListener?
Is this a good solution at all? I also tried to add a second listener, which calls the TemplateGuesser, its the service sensio_framework_extra.view.listener with the class Sensio\Bundle\FrameworkExtraBundle\EventListener\TemplateListener But that didn't work.
Whenever you need to add custom logic or extend the framework behaviour, you can use and abuse the container configuration. That means you can overwrite pretty much every service Symfony defines by just creating a new class that extends that service – or not, really – and creating the service definition for it with the same key as the original service you wanted to extend or change behaviour.
For instance, Symfony has a base template guesser registered as a service with the sensio_framework_extra.view.guesser id. If you want to extend that or change behaviour, you only need to create your own class and register it with the same id of the original service – remember that the bundles loading order affects the service definitons with the same id, where the last one loaded is the one that will be created.
That should solve both of your problems.
I'm working on a Symfony2 project and am trying to figure out how to pass parameters from the route configuration to the controller. I know I can configure default values in the route configuration, and retrieve the values in the controller using the appropriate var name in the function declaration, but that isn't exactly what I want.
My use case is the following. I have a standard method in my controller that I want to access from 2 or 3 different routes. Depending on which route is being called, I want to "configure" the method differently. I can accomplish this in a few ways:
In my controller, check the route name using `$this->container->get("request")->get("_route"), but that is ugly, and then I am hardcoded to the route name. Moves configuration to the controller, which should just be logic - not configuration.
Create a base controller class, and subclass each method for my different routes. Each subclassed method would then have the necessary configuration within the method. Cleaner soln than #1, but still "heavy" in the sense of having multiple classes for a simple need and still pushes configuration data into the business logic.
Put configuration data into the route configuration. In the controller, access the configuration data as required. Ideal solution, but don't know how.
I can use the route default array to specify my arguments, but then must make sure to use a regex to ensure that the params are not overridden at the URL level (security risk). This is functional, but still kinda cludgy and not a pretty hack.
I presume that there must a better way to do this, but I can't seem to figure it out. Is there a way to access the routing object from the controller, and access the different configuration parameters?
You can pull the actual route from the router service. Something like:
$routeName = $this->container->get("request")->get("_route");
$router = $this->container->get("router");
$route = $router->getRouteCollection()->get($routeName);
Not sure if this would be such a great design though. Consider passing a $configName to your controller method, adding a parameter with the same name in a config file then using getParameter to access it. That would eliminate the route stuff from the equation.
Something like:
zayso_arbiter_import:
pattern: /import
defaults: { _controller: ZaysoArbiterBundle:Import:index, configName: 'someConfigName' }
public function importAction(Request $request, $configName)