php - Symfony3 sub request lose of session -


i experience strange behavior when doing sub requests symfony 3.

the context

i think it's better explain why leads problem, may find solution. can skip part if it's read.

i've developped kind of clone of api platform, not fork, inspired rewrite. 1 of functionality wanted add ability call api server side.

the api lot of work (works relations example) it's useful let work of persisting / filtering, etc, classic server side app (no ajax calls).

the simplest way i've found sub requests. current implementation looks when used :

// collection of articles (output array) $this->proxy->get(article::class)->collection($page, $itemsperpages, $filters, $ordering)->asarray();  // single article (output entities) $this->proxy->get(article::class)->item('a2ck2')->asobject();  // persist article (output entities) $this->proxy->persist(article::class)->item(['title' => 'super article'])->asobject(); 

you idea.

when call as* method, request executed, , code simple :

// proxy.php public function execute(request $request, response &$response = null) {     $response = $this->kernel->handle($request);      [...]     // handle response status code, content etc. not important here. } 

the request given in parameter of execute method built (here builder shown):

// getrequestbuilder.php protected function createrequest(): request {     $currentrequest = $this->getcurrentrequest();     $request = request::create(         $this->generateuri([...]),         request::method_get,         [],         $currentrequest->cookies->all()     );     return $request; } 

the problem

a problem occurs when have multiple firewalls , when sub request matches route in different firewall 1 of original request.

for following security configuration :

# app/config/security.yml security:     encoders:         appbundle\entity\user:             algorithm: bcrypt      providers:         main:             id: app.main_user_provider         doctrine:             entity:                 class: appbundle:user                 property: username      firewalls:         backend:             pattern: ^/admin             anonymous: ~             logout:                 path:   /admin/logout                 target: /admin/login                 invalidate_session: true             stateless: false             guard:                 entry_point: app.backend.login_form_authenticator                 authenticators: [app.backend.login_form_authenticator]         frontend:             pattern: ^/             anonymous: ~             logout:                 path:   /logout                 target: /login                 invalidate_session: true             stateless: false             guard:                 entry_point: app.frontend.login_form_authenticator                 authenticators: [app.frontend.login_form_authenticator] 

if sub request admin route route matching frontend firewall, lose admin session.

if dump session before , after api call, gives me following :

array (size=3)   '_security.backend.target_path' => string 'http://localhost/admin/api/formation/categories' (length=51)   '_csrf/form' => string 'wt9js9b8det00xanugeq23qxfqy8uhrt_j5i6d9btj8' (length=43)   '_security_backend' => string 'c:67:"symfony\component\security\guard\token\postauthenticationguardtoken":1786:{a:2:{i:0;s:7:"backend";i:1;s:174'... (length=1868) 

and after sub request :

array (size=2)   '_security.backend.target_path' => string 'http://localhost/admin/api/formation/categories' (length=51)   '_csrf/form' => string 'wt9js9b8det00xanugeq23qxfqy8uhrt_j5i6d9btj8' (length=43) 

the _security_backend key gone, , session.

if don't copy cookies of original request sub request, session not lost, have problem if api route secured:

// getrequestbuilder.php protected function createrequest(): request {     $currentrequest = $this->getcurrentrequest();     $request = request::create(         $this->generateuri([...]),         request::method_get,         [],         // removing line , replace empty array solves problem of loosing session.         // if target route behind "backend" firewall, sub request redirected login page.         $currentrequest->cookies->all()     );     return $request; } 

my questions

1) see think method of doing sub requests robust enough or know better way achieve same result?

on side note: don't curl or other way real http requests because want ability entities (actual objects) result of api call.

2) know way prevent original session lost if sub request matches route different firewall? understand right now, way see detect (no idea how..) if target route on same firewall or not, , copy cookies if so.. seems hard , hard have stable. , looks dirty **.

any idea appreciated.

thanks help.

i post own answer because found ugly way seems work handle case, feel really dirty , greatful if can think of clean way handle case.

so solution "backup" session data before request , restore after... did this:

// proxy.php public function execute(request $request, response &$response = null) {     try {         $this->savesession();         $response = $this->kernel->handle($request);          [...]         // handle response status code, content etc. not important here.     } {         $this->restoresession();     } }  /**  * saves current session.  */ private function savesession() {     $this->sessionstack[] = (array)$this->session->all(); }  /**  * restores latest session saved using savesession().  */ private function restoresession() {     $data = array_pop($this->sessionstack);     $this->session->clear();     foreach ($data $k => $v) {         $this->session->set($k, $v);     } } 

and, of course, still copy cookies of current request in sub-request.

it's basic seems work (for current case @ least). have no idea of side effects of copying session data this, can guess it's bad thing.

it works because need keep _security_backend key serialized object, "backupable" string. if in future cases session holds real objects being modified in sub-request, not work @ all.

and performance if session holds lot of data? hmm

so if of have better solution, i'm ears :)


Comments

Popular posts from this blog

php - Vagrant up error - Uncaught Reflection Exception: Class DOMDocument does not exist -

vue.js - Create hooks for automated testing -

Add new key value to json node in java -