在所有网络应用中,您可以获取/设置会话变量
PHP:
$foo = $_SESSION['myVar'];
.NET (MVC,在Controller中):
using System.Web.Mvc; // ... var foo = Session["myVar"];
我正在寻找关于会话变量的一些详细信息:
硬盘,内存,......
客户端/服务器
Web服务器(Apache,IIS,...)/ Web App
会议,对。所以当会话开始时,它何时结束以及系统如何知道它何时可以摆脱这些变量(GC机制)?
PS:我想让这里的人们建立一个关于这个概念的好文档。如果您认为应该添加或编辑某些问题,请随时编辑问题。
答案 0 :(得分:3)
<强>目的强>
创建会话变量主要是为了处理HTTP协议的无状态行为。由于每个页面请求几乎完全与其他页面请求分开处理,因此开发人员希望将各种请求串联在一起。这个规范示例是一个登录页面,用于对用户进行身份验证,然后在登录后更改请求页面的行为。
为了解决这个问题,许多语言和/或框架都提供了一个会话变量的概念,它允许开发人员存储与特定浏览器相关联的数据,并且可以在来自同一浏览器的单独请求中保留。
因此,以登录为例,在新浏览器的第一个请求中,会话变量将为空。然后,用户将填写认证信息并假设它是正确的,在服务器端,代码将为该浏览器设置会话变量以包含某种标识符,以表明他的浏览器已经过认证。然后在后续请求期间,代码可以检查会话变量中的标识符,以执行一些需要登录的特定代码。
另一个常见用例是&#34;向导&#34;流程。您可能希望用户通过多个单独的请求填写多页表单。当用户填写表单时,您可以将值添加到会话中,直到用户到达表单的末尾,此时您可以将其保存在更永久的存储中。
存储和管理
存储会话变量的方法有很多种。任何类型的持久存储都可以在请求中保持不变。可能最基本的方法是为每个会话创建一个单独的文件。 PHP通过获取它在浏览器中存储为cookie的会话ID,然后查找具有从会话ID派生的命名的文件来完成此操作。
您还可以将会话变量存储在数据库,共享内存中,甚至存储在cookie本身中。 Ruby on Rails通过加密数据然后将cookie设置为加密数据来存储会话变量。因此会话存储在用户的浏览器本身中。
最常见的是,会话变量与以某种方式存储在Web浏览器中的cookie相关联。此cookie通常由编写Web服务器应用程序的语言或框架自动管理。语言或框架检测新会话并创建新的会话变量,它通过某种API提供给Web服务器应用程序。然后,Web服务器应用程序可以使用API在会话变量中存储信息,删除它,创建新的等等...通常框架在会话的生命周期中有一些默认值,但通常可以通过API。我认为最典型的默认生命周期是浏览器进程的生命周期,通过cookie与用户的浏览器进程相关联。
安全强>
会话变量存在很多安全问题,因为它们通常用于管理Web应用程序中的授权和身份验证。
例如,许多应用程序仅使用与cookie关联的生命周期来设置会话生命周期。许多登录系统希望强制用户在指定时间后重新登录,但是当您告知cookie时,您无法信任浏览器使cookie过期。浏览器可能是错误的,可能由恶意的人编写,或由用户自己操纵以调整cookie的生命周期。因此,如果您使用的会话变量API依赖于cookie生存期,您可能需要具有强制会话变量过期的辅助机制,即使cookie没有。
其他一些安全问题涉及存储。如果您将会话ID存储在cookie中,然后使用该会话ID作为文件名来存储会话变量,则恶意浏览器可以将cookie中的会话ID更改为另一个ID,然后来自该浏览器的请求将开始使用某些ID其他浏览器的会话文件。
另一个问题是被盗的会话信息。通过XSS或数据包检查,会话信息可以从用户浏览器会话中被窃取,然后被恶意用户用来访问其他用户的帐户。通常使用SSL来保护传输中的会话,从而减轻此类问题。
This page解释了使用PHP实现的Session Variables时的许多安全问题。 Ruby on Rails的a similar page概述了该平台的Session Variables的安全问题。
答案 1 :(得分:2)
所以,我将在两个考虑因素的基础上提出这个问题: 1.我正在根据PHP指南回答。 2.我假设使用了共享托管服务。
<强>存储强> 通过使用共享主机,php.ini文件保留了这个答案。该文件是通过php.ini文件中的“session.save_path”行在您指定的路径上物理创建的。
谁存储会话 会话由SERVER技术上存储,但显然是由客户端请求。那么,回答:SERVER。 资料来源:session_start
由谁管理 如果您的session.save_path设置为在共享主机服务器上的某个位置,那么它们将控制销毁它的GC或忽略它直到稍后。实际上,我发生了一些实例,其中共享主机服务器中的其他客户端的session_gc.maxlifetime的数量比我的数量少,因此会导致我的会话文件在其设置的时间内被破坏(其他共享用户) 。要解决此问题,请在您的OWN文件树中编辑“session.save_path”。
<强>寿命强> 如前所述,“session.gc_maxlifetime”控制此文件的“到期”。与此同时,应考虑“session.gc_probability”和“session.gc_divisor”,并分别设置为“1”和“100”。谷歌搜索这个以获得进一步的解释。
安全强> 我要让php.net处理这个,但这是链接!
来源:Security
答案 2 :(得分:2)
我以ASP.NET应用程序场景为例。
在ASP.NET / MVC中HttpContext.Current.Session
提供对由服务器(WebServer / AppServer,IIS)管理的RAM的访问。在Internet Information Server的情况下,使用的RAM位于所谓的应用程序池内,并由在Web- / AppServer内运行的一个或多个应用程序使用。从程序员的角度来看,结构是一个字典,意思是通过C#进行访问,你可以使用this []操作符来写入和读取Session对象。
// write access
var CurrentArticle = 123456;
Session["CurrentArticle"] = CurrentArticle;
//...
// read access
var CurrentArticle = 0;
CurrentArticle = (int)Session[nameof(CurrentArticle)];
.NET提供的Session对象将在方法Session_Start
中创建,并在Session_End
中删除。但是,您不必使用系统的默认会话存储,并且可以实现自己的会话存储,例如:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;
using System.Web;
// using MyOtherStuff;
namespace MyStuff.Server.Context
{
public class HttpSessionState : HttpSessionStateBase
{
Dictionary<string, object> _sessionStorage = new System.Collections.Generic.Dictionary<string, object>();
public override object this[string name]
{
get
{
if (HttpContext.Current == null || HttpContext.Current.Session == null)
if (!_sessionStorage.ContainsKey(name))
return null;
else return _sessionStorage[name];
return HttpContext.Current.Session[name];
}
set
{
if (HttpContext.Current == null || HttpContext.Current.Session == null)
_sessionStorage[name] = value;
else HttpContext.Current.Session[name] = value;
}
}
}
public class Current
{
/// <summary>
/// Objects stored in Cache expire after some time; compare Application
/// </summary>
public static ExpiringCache Cache = new ExpiringCache();
/// <summary>
/// Objects stored in Application don't expire
/// </summary>
public static Application Application = new Application();
public static HttpSessionState Session = new HttpSessionState();
private static System.Web.HttpServerUtility server;
public static System.Web.HttpServerUtility Server
{
get
{
if (System.Web.HttpContext.Current != null)
return Context.Current.Server;
if (server != null)
return server;
server = new System.Web.HttpApplication().Server;
if (server != null)
return server;
throw new NotSupportedException("HDitem.ApplicationServices.Current was not initialized (server)");
}
set { server = value; }
}
}
//..
}
连接到服务器的每个新浏览器都会创建一个新会话。如果您不关心同一用户的最近会话数据(如果您的应用程序有用户),那么您可能不会在此处完成。
如果您想将新会话重新连接到一个或多个以前的会话,即通过您可以获得的有关此用户的某些数据组合(例如通过请求,cookie或类似)或以最简单的形式识别用户身份验证比您可能希望在Session_End中存储会话数据而不是删除它并在Session_start中或之后的任何时间恢复(一旦您有足够的关于此会话的用户的数据来识别她。)如果您需要任何形式的会话持久性(大概可以归结为硬盘或SSD来引用您的问题),在这种情况下可以采用任何形式的基于每个用户的存储,有时存储在用户配置文件中数据库或任何文件格式,如基于XML或JSON的。
换句话说:我不想在这里概括太多,但会话存储理想情况下是非常快的内存存储,如果实现会话持久性,可能会保存到任何外部存储。
上面提到的会话存储位于服务器端。现代浏览器有一个内置的本地存储,可以通过JavaScript访问。此本地存储还可用于创建会话内存,该会话内存可以与服务器端会话不同地使用,但当然可以以显式请求或附件(cookie)的形式进行同步。