http相关知识

来源:互联网 发布:单片机红外发射程序 编辑:程序博客网 时间:2024/06/03 20:53

 http相关知识 - (2)状态管理 - session


1. Session原理


(1)Session用于存储特定的用户会话所需的信息。Session对象的引入是为了弥补无状态HTTP协议的不足。

(2)系统为每个用户都设立一个独立的Session,用以存储Session变量,并且各个用户的Session对象互不干扰。

(3)在服务器端有一个session池,用来存储每个用户提交session中的数据,Session对于每一个客户端(或者说浏览器实例)是“人手一份”,用户首次与Web服务器建立连接的时候,服务器会给用户分发一个SessionID作为标识。SessionID是一个由24个字符组成的随机字符串。用户每次提交页面,浏览器都会把这个SessionID包含在HTTP头中提交给Web服务器,这样Web服务器就能区分当前请求页面的是哪一个客户端,而这个SessionID是一cookie的方式保存的在客户端的内存中的,如果想要得到Session池中的数据,服务器就会根据客户端提交的唯一SessionID标识给出相应的数据返回。

(4)Session与Cookie是紧密相关的。 Session的使用要求用户浏览器必须支持Cookie,如果浏览器不支持使用Cookie,或者设置为禁用Cookie,那么将不能使用Session。Session与Cookie是紧密相关的。 Session的使用要求用户浏览器必须支持Cookie,如果浏览器不支持使用Cookie,或者设置为禁用Cookie,那么将不能使用Session。


2. Session配置

    <system.web>      <sessionState mode="Off|InProc|StateServer|SQLServer"      cookieless="true|false"      timeout="number of minutes"      stateConnectionString="tcpip=server:port"      sqlConnectionString="sql connection string"      stateNetworkTimeout="number of seconds"/>    </system.web>
mode:设置将Session信息存储到哪里
        a. Off:不使用Session功能; 
        b. InProc :将Session存储在IIS进程内,这是默认值,也最常用(优点是简单,性能最高。但是当重启IIS服务器时Session丢失。); 
        c. StateServer :将Session存储在ASP.NET状态服务进程中(重新启动Web应用程序时保留会话状态,并使会话状态可以用于网络中的多个Web服务器。); 
        d. SQLServer :将Session存储在SQL Server中(存储在内存和磁盘中,服务器挂掉重启后都还在)。
cookieless:设置客户端的Session信息存储到哪里
        a. ture 使用Cookieless模式;这时客户端的Session信息就不再使用Cookie存储了,而是将其通过URL存储。
        b. false 使用Cookie模式,这是默认值。
timeout 设置经过多少分钟后服务器自动放弃Session信息。默认为20分钟。 
stateConnectionString 设置将Session信息存储在状态服务中时使用的服务器名称和端口号,例如:"tcpip=127.0.0.1:42424”。当mode的值是StateServer是,这个属性是必需的。(默认端口42424)。 
sqlConnectionString 设置与SQL Server连接时的连接字符串。例如"data source=localhost;Integrated Security=SSPI;Initial Catalog=joye"。当mode的值是SQLServer时,这个属性是必需的。
stateNetworkTimeout 设置当使用StateServer模式存储Session状态时,经过多少秒空闲后,断开Web服务器与存储状态信息的服务器的TCP/IP连接的。默认值是10秒钟。

3. Session操作

            //写入            Session["UserName"] = "Rod Chen";            //读取            var userName = Session["UserName"].ToString();            Response.Write(userName);            //遍历            IEnumerator sessionEnum = Session.Keys.GetEnumerator();            while (sessionEnum.MoveNext())            {                Response.Write(Session[sessionEnum.Current.ToString()].ToString() + " ");            }            //销毁            Session.Abandon(); //结束会话            Session.Clear();//不结束会话

4. Session问题(C#)

(1)Session.SessionId什么时候返回客户端?
(2)如何在session过期的时候跳出系统或者跳到指定页面?
(3)Session_Start,Session_End?

接下来将会以一个案例说明上面的几个问题:

5. 案例(源码:https://github.com/rodchen-king/http/tree/v1.1)

(1)首先是第一个问题(这个SessionId其实对应的会返回到前端一个名为ASP.NET_SessionId的cookie):
        a. 首先看一下整个项目的初始action(Home/Index)
        public ActionResult Index()        {            //页面初始访问就已经产生session。            var sessionId = Session.SessionID;            ViewBag.Message = "修改此模板以快速启动你的 ASP.NET MVC 应用程序。";            return View();        }

        b. 启动项目然后查看Index方法中sessionId的值,此时server已经对于当前的用户产生session,但是前端却没有这个session对应的cookie值。
    

        c. 针对上面的情况具体的原因我不知道,如果有知道的可以说一下。接下来我在Index的action中加了行代码,然后在查看前端是否含有这个cookie。通过下面的图片大家可以看到此时已经有了这个cookie,其中cookie是在客户端访问不了的,可以看一下这个cookie的属性,有什么问题可以看一下http相关知识 - (2)状态管理 - cookie

        d. 上面说的是第一种方式返回这个cookie,现在说一下第二种情况。在Global.asax文件中添加session的方法,这样的话也可以返回cookie值到前端。
    public class MvcApplication : System.Web.HttpApplication    {        protected void Application_Start()        {            AreaRegistration.RegisterAllAreas();            WebApiConfig.Register(GlobalConfiguration.Configuration);            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);            RouteConfig.RegisterRoutes(RouteTable.Routes);            BundleConfig.RegisterBundles(BundleTable.Bundles);            AuthConfig.RegisterAuth();        }        void Session_Start(object sender, EventArgs e)        {        }        void Session_End(object sender, EventArgs e)        {        }    }


(2)第二个问题:这个地方希望大家记住问题一种的cookie,因为所有的请求中都会带有着cookie,这也是验证cient端是否是当前的这个用户。因为是对所有的请求都要验证,在asp.net 使用filter机制来进行这样的check。

using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Web;using System.Web.Mvc;using System.Web.Routing;namespace http_study.Filter{    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]    public class AuthorizationFilter: FilterAttribute, IAuthorizationFilter    {        public void OnAuthorization(AuthorizationContext filterContext)        {            //因为对于需要登录的application,其实有些界面是不需要进行验证,这里的skipAuthorization就是来判断是否需要进行验证,这里是标注如果访问的action的controller或者action本身有NoFilter 的Attribute,则不需要进行验证。            bool skipAuthorization = filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(NoFilter), true) ||                filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true);            if (!skipAuthorization)             {                string sessionCookie = filterContext.HttpContext.Request.Headers["Cookie"];                //这个地方是判断前端发的请求是否含有ASP.NET_SessionId,如果没有的话则需要跳转到系统的初始界面。                if ((null != sessionCookie) && (sessionCookie.IndexOf("ASP.NET_SessionId") <= 0))                {                    if (filterContext.HttpContext.Request.IsAjaxRequest() == true)                    {                        //如果是ajax发过来的请求,就需要返回error,然后在前端进行页面的跳转,因为ajax的请求是不能进行重定向的。                        AjaxRequestLogout(filterContext);                    }                    else                    {                        //如果不是ajax的请求,则使用重定向进行页面的跳转。                        RouteValueDictionary redirectTargetDictionary = new RouteValueDictionary();                        redirectTargetDictionary.Add("action", "Index");                        redirectTargetDictionary.Add("controller", "Home");                        redirectTargetDictionary.Add("timeout", "true");                        filterContext.Result = new RedirectToRouteResult(redirectTargetDictionary);                    }                }                else if (filterContext.HttpContext.Session == null || filterContext.HttpContext.Session["UserName"] == null)                {                    //这地方是判断server的session有没有过期,如果过期的话进行页面的跳转,也分为两种情况,和上面的一样,这里就不在赘述了。                    if (filterContext.HttpContext.Request.IsAjaxRequest() == true)                    {                        AjaxRequestLogout(filterContext);                    }                    else                    {                        RouteValueDictionary redirectTargetDictionary = new RouteValueDictionary();                        redirectTargetDictionary.Add("action", "Index");                        redirectTargetDictionary.Add("controller", "Home");                        redirectTargetDictionary.Add("timeout", "true");                        filterContext.Result = new RedirectToRouteResult(redirectTargetDictionary);                    }                }            }        }        //如果ajax发过来的请求,需要自己构造response返回exceptino,然后在前端检测返回的error就行页面跳转。        private void AjaxRequestLogout(AuthorizationContext filterContext)        {            filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;            JsonResult jsonResult = new JsonResult();            jsonResult.Data = new            {                Priority = 1,                Caption = "SessionExpire",                Message = "TimeOut"            };            jsonResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;            filterContext.Result = jsonResult;        }    }}

        b. 我们再看一下对应的前端的处理 ,将ajaxError 绑定到document上面,这样的所有的error都会冒泡到这个方法里,然后对其中的值进行检查,然后进行页面的跳转。

$(function () {    $(document).ajaxError(            function (event, xhr, options, exc) {                if (xhr.status == 500 && JSON.parse(xhr.responseText).Caption == "SessionExpire") {                    window.location = '/Home/Index';                }            }    );});

针对上面的这案例可以到我的github下载源文件进行查看

(3)接下来就是第三个问题了:
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Http;using System.Web.Mvc;using System.Web.Optimization;using System.Web.Routing;namespace http_study{    // 注意: 有关启用 IIS6 或 IIS7 经典模式的说明,    // 请访问 http://go.microsoft.com/?LinkId=9394801    public class MvcApplication : System.Web.HttpApplication    {        protected void Application_Start()        {            AreaRegistration.RegisterAllAreas();            WebApiConfig.Register(GlobalConfiguration.Configuration);            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);            RouteConfig.RegisterRoutes(RouteTable.Routes);            BundleConfig.RegisterBundles(BundleTable.Bundles);            AuthConfig.RegisterAuth();        }        void Session_Start(object sender, EventArgs e)        {            var sessionValue = HttpContext.Current.Session;        }        void Session_End(object sender, EventArgs e)        {            var sessionValue = HttpContext.Current.Session;        }    }}

上面有两个方法,Session_Star, Session_End方法,字面意思大家也知道是做什么用的了吧。在介绍执行之前想给session的过期时间设置的短一点,最上面有介绍过session在web configure的配置,这里我们把过期时间改为一分钟。

<sessionState mode="InProc"      cookieless="false"      timeout="1"      stateConnectionString="tcpip=server:port"      sqlConnectionString="sql connection string"      stateNetworkTimeout="10"      />

        a. 然后启动我们项目在上面的两个方法里加上断点,我们去看一下其中的值。此时是执行到了Session_star,因为server对用户的访问产生一个唯一标识的id。



        b. 接下来跳过断点,然后等一分钟,你可以下载代码执行,然后计时一分钟看会不会自动执行到Session_end方法里。



        c. 相信大家看到此时的Current是null,为什么呢?我网上查了一下HttpContext对象。
HttpContext :获取或设置与当前线程相关联的主机上下文。二个关键词:【当前线程】,【关联】。
HttpContext.Current获取到与【当前请求】相关的HttpContext对象。

所以当我们的session过期的时候,这个针对当前用户这个线程都已经没有了,所以用户需要重新访问去拿新的session,用户如果是登录之后的,就需要我们写相关session过期的处理,让用户跳出整个系统。


6. cookie与session的区别


1.cookie 是一种发送到客户浏览器的文本串句柄,并保存在客户机硬盘上,可以用来在某个WEB站点会话间持久的保持数据。
 
2.session其实指的就是访问者从到达某个特定主页到离开为止的那段时间。 Session其实是利用Cookie进行信息处理的,当用户首先进行了请求后,服务端就在用户浏览器上创建了一个Cookie,当这个Session结束时,其实就是意味着这个Cookie就过期了。
注:为这个用户创建的Cookie的名称是aspsessionid。这个Cookie的唯一目的就是为每一个用户提供不同的身份认证。

3.cookie 和session的区别是:cookie数据保存在客户端,session数据保存在服务器端。

4.cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
   考虑到安全应当使用session。

5.session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
   考虑到减轻服务器性能方面,应当使用COOKIE。

6.单个cookie保存的数据不能超过4K(本人没有测过,有知道怎么测的可以去测一下),很多浏览器都限制一个站点最多保存20个cookie。

以上的内容都是自己在学习的过程中的一些记录,有不正之处希望指出!

0 0
原创粉丝点击