politica - usar cookies en laravel
Laravel compartió el problema de detección de cookies en dominio y subdominio (3)
Debe implementar su propia "recuperación" y "configuración" de una cookie.
Recuperar (tiene, obtener) cookies
Cree una nueva clase (en cualquier lugar que desee, pero haría la aplicación / Foundation / Facades / ) con el nombre Cookie.
use /Illuminate/Support/Facades/Cookie as CookieStock;
class Cookie extends CookieStock {
//implement your own has(...);
public static function has($key)
{
return ! is_null(static::$app[''request'']->cookie(PREFIX . $key, null)); //get the prefix from .env file for your case APP_ENV
}
//implement your own get(...);
public static function get($key = null, $default = null) {...}
}
Ahora abra config / app.php y cambie el alias correspondiente (cookie).
Configurando (hacer) cookies
Cree un nuevo proveedor (use artisan) y copie y pegue el código de Illuminate / Cookie / CookieServiceProvider.php y cambie los espacios de nombres. Nuevamente, abra config / app.php y cambie el proveedor de servicio correspondiente con el nuevo.
Cree una nueva clase (en cualquier lugar que desee, pero haría la aplicación / Foundation / Cookie / ) con el nombre CookieJar.
use /Illuminate/Cookie/CookieJar as CookieJarStock;
class CookieJar extends CookieJarStock {
//Override any method you think is relevant (my guess is make(), I am not sure at the moment about queue related methods)
public function make($name, $value, $minutes = 0, $path = null, $domain = null, $secure = false, $httpOnly = true)
{
// check before applying the PREFIX
if (!empty($name)) {
$name = PREFIX . $name; // get the PREFIX same way as before
}
return parent::make($name, $value, $minutes, $path, $domain, $secure, $httpOnly);
}
}
Actualice el código en su propio proveedor de servicios de cookies para usar su implementación de CookieJar (línea 19).
Ejecute $ composer dump-autoload
, y debería estar listo.
Actualizar
Desde que apareció BorisD.Teoharov, que si el marco cambia la firma de make()
de CookieJarStock
(o cualquier otra función relacionada con cookies) entre las versiones principales, hice un repository ejemplo, que incluye una prueba que puede usarse tal como está y está fallará si ocurre el cambio de firma.
Es tan simple como esto:
public function test_custom_cookie_jar_can_be_resolved()
{
resolve(/App/Foundation/Cookie/CookieJar::class);
$this->assertTrue(true);
}
Detallado cómo se puede inspeccionar en el correspondiente commit dif .
Estoy trabajando en Laravel 5.4.30.
Imagina que tenemos un dominio example.com
y un subdominio de dev.example.com
. El dominio principal es para la rama maestra y el subdominio dev es para desarrollar la rama. Tenemos un sistema de aviso de cookies que se ocultará después de hacer clic en el botón Hide Cookie Notice
. Esto funciona configurando una cookie para siempre. Hemos establecido las configuraciones SESSION_DOMAIN en cada dominio para cada entorno.
Para el dominio principal:
SESSION_DOMAIN=example.com
Para el subdominio de desarrollo:
SESSION_DOMAIN=dev.example.com
Ahora el tema viene de aquí. Si vamos a example.com
y hacemos clic en ocultar el aviso de cookie, se establecerá una cookie para siempre para el dominio principal. Después de eso vamos a dev.example.com
y hacemos lo mismo. Por lo tanto, también se establecerá una cookie para el subdominio. Pero esta cookie se ha establecido después de la anterior. (El orden es importante) ¡Ahora si renovamos el subdominio, veremos ese aviso nuevamente! (no oculto) El navegador ha leído la cookie principal debido a .example.com
configurado en el parámetro de domain
de cookie en el navegador, por lo que todos los subdominios se verán afectados. Pero la vista aún muestra el aviso porque no puede leer ninguna cookie para ocultarlo.
De todos modos no quiero compartir esa cookie en todos los subdominios. ¿Cómo puedo lograr eso? Creo que debería agregar un prefijo para el nombre de la cookie. Pero no sé cómo hacerlo, que laravel agrega automáticamente el prefijo al nombre de la cookie.
¿Alguna solución?
He configurado entornos de prueba para asegurarme de que no me faltan detalles.
Como en mi respuesta anterior, pensé que la invalidación de las cookies será suficiente para ese caso, pero como @BorisD sugirió que no es así, y lo he confirmado en mis pruebas.
Así que hay algunas notas importantes, que vienen de mis experiencias ...
- No mezcle las versiones de Laravel en subdominios : si usa SESSION_DOMAIN , debe asegurarse de que su versión de Laravel coincida (entre la raíz y los subdominios), porque he experimentado con 5.4 bajo el dominio example.com y 5.6 bajo dev.example.com. Esto me mostró cierta incoherencia al tratar con las cookies, por lo que se han realizado algunos cambios importantes entre estas versiones, y puede estar seguro de que no funcionará correctamente si mezcla versiones. Finalmente terminé con Laravel 5.6 en ambos dominios , así que no estoy 100% seguro de que funcione en Laravel 5.4, pero creo que debería.
- Asegúrese de que todos sus subdominios utilicen el mismo APP_KEY ; de lo contrario, Laravel no podrá descifrar la cookie, devolviendo un valor
null
, ya que todo el cifrado / descifrado en Laravel usa esta clave de aplicación ... - SESSION_DOMAIN . En SESSION_DOMAIN he apuntado el mismo dominio raíz como
example.com
para ambos dominios. Con esta configuración, puedo crear una cookie en el dominio raíz y recuperarla correctamente en ambos dominios. Después de esa configuración, la creación de una cookie en un subdominio obliga al dominio raíz a recibir un nuevo valor de la cookie de subdominios también, y se anulan Así que supongo que todo funciona aquí como se solicita en la pregunta original. Parámetros de creación de cookies : en caso de que desee utilizar un subdominio en SESSION_DOMAIN, también puede hacerlo de forma segura. Sin embargo, debe asegurarse de que las llamadas "cookies globales" se definan de una manera un poco diferente. Cookie hace sintaxis:
Cookie make(string $name, string $value, int $minutes, string $path = null, string $domain = null, bool $secure = false, bool $httpOnly = true)
Entonces, lo que es importante aquí, debe poner su dominio raíz para esta cookie en particular en la creación de esta manera, por ejemplo:
return response($content)->cookie(''name'',''value'',10,null,''example.com'')
Conclusiones:
- Con esta configuración, debería poder acceder a sus Cookies de manera adecuada en subdominios y su dominio raíz.
- Probablemente deba actualizar sus instalaciones de Laravel a 5.6, lo que lo obligará a actualizar a PHP 7.1 al menos (también hubo algunos cambios en las cookies en php)
- Y finalmente, en su código, no confíe en la existencia de Cookie, sino solo en sus valores (no sé si ese es su caso).
Puede establecer un prefijo para el nombre de la cookie en función del entorno.
Primero, agregue COOKIE_PREFIX
a su archivo env.
COOKIE_PREFIX=dev
Entonces, utilízalo al configurar tu cookie
$cookie = cookie(env(''COOKIE_PREFIX'', ''prod'') . ''_name'', ''value'', $minutes);
Luego, recuperarlo así
$value = $request->cookie(env(''COOKIE_PREFIX'', ''prod'') . ''_name'');