无状态http
一个浏览者发出的请求通常都是由实现了IhttpHandler接口的对象进行响应,由于下次访问不一定还是上次那个对象进行响应,上次响应完毕后对象可能已经销毁了,写的类变量值早已经不存在了,因此了不要把状态信息保存到变量当中.浏览器和服务器使用Socket通信,服务器将请求结果返回给浏览器后,会关闭当前Socket连接。而且服务器会在处理页面完毕后销毁页面对象。应用层面的原因是:浏览器和服务器之间通信都遵守HTTP协议.
客户端的状态保持方案:ViewState、隐藏域、Cookies、控件状态、URL查询参数
服务端的状态保持方案:Session(会话)、Application、Caching(缓存)、DataBase(数据库)
Cookie
如在页面显示欢迎你的标语,或者让你不用输入ID、密码就直接登录等等。Cookie不兼容浏览器!(不同浏览器不共享Cookie文件数据)
HttpCookie cok = new HttpCookie(“uId”, “10001”);//(“键”,”值”)
cok.Expires = DateTime.Now.AddDays(18);//设置失效日期-现在之后的18天后
context.Response.Cookies.Add(cok); //添加到响应中
string strUName=context.Request.Cookies[“uId”].Value;//从请求中获得Cookie
cookie的一些注意点
session Session提供了一种把信息保存在服务器内存中的一种方式。它能存储任何数据类型包括自定义对象。
每个客户端的Session是独立存储。
Session 对象用于存储有关用户的信息。
在整个用户会话过程中都会保留此信息。(保存SessionId的cookie丢失之前)
当用户在应用程序中从一个网页浏览到另一个网页时,存储在 Session 对象中的变量不会被丢弃。
Session只可由该会话的用户访问(因为SessionId的东东以cookie的方式保存访问者浏览器的缓存里了)
用户不能访问或修改他人的Session
利用Cookie与Session的一则简单的登陆Demo
从一些后台网站上扣了个页面回来,稍加改动:如下图:
首先搞定一件事,验证码,我从别的地方找到一个写验证码的类,遂直接拿了过来使用,建立一个一般处理程序用来操作验证码,具体代码如下:
public class CreatValidateCode : IHttpHandler,IRequiresSessionState//一般处理程序需要 session的话,实现此接口 { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "image/jpeg"; Common.ValidateCode validateCode =new Common.ValidateCode(); //创建验证码随机字符串 string str = validateCode.CreateValidateCode(4); //将字符串转成 验证码的图片 validateCode.CreateValidateGraphic(str,context); //验证码交给客户端的时候,将验证码 放到 session context.Session["ValidateCode"] = str; }
我们把产生的验证码写入带session当中,以防止用户暴力破解,让后再做个小功能,让用户点击验证码能够实现切换验证码的功能,这个我们可以Javascript帮助我们来完成,这里我使用了jquery来做切换图片的功能,后面地址加"1"主要是为了兼容IE
$(function () { $("#Image1").click(function () { //先把当前 图片的 url地址取出来。 var originUrl = $(this).attr("src"); //给当前 图片的src地址设置一新的地址 $(this).attr("src", originUrl + 1); });
验证码的功能搞定后,下面我们可以登陆逻辑了,这里的文本框都是用普通的html标签,好了开始写登陆逻辑了
首先了第一次请求过来,先从cookie中获取已经登录过的用户名,放到文本框中,提高用户的体验,后续请求再来的时候,直接从表单里面获取值,在放到文本框里面去
protected void Page_Load(object sender, EventArgs e) { if(!IsPostBack)//第一次请求过来,先从cookie中获取已经登录过的用户名,放到文本框中,提高用户的体验 { PreUserName = Request.Cookies["UserName"] == null ? string.Empty : Request.Cookies["UserName"].Value; } else { //后续请求再来的时候,直接从表单里面获取值,在放到文本框里面去 PreUserName = Request["txtLoginName"]; } }
首先我们提交的时候首先要对验证码进行校验,具体的做法就是取出session跟用户请求的验证码是否一致,这一步要在其他验证之前
//取出发送给当前客户端的验证码 string sendCode = Session["ValidateCode"] == null ? string.Empty : Session["ValidateCode"].ToString(); string recieveCode = Request["txtCode"]; if (!sendCode.Equals(recieveCode)) { Js = "<script>alert('验证码不正确')</script>";//推荐大家使用这种方式。来往前台传递js脚本 return;
}
下面开始校验用户名跟密码,我写的比较简单,用的三层来写的,首先获取用户的请求,然后从数据库中查出是否存在这个用户,存在就写入session当中,并且把用户名写入到cookie中,我剩了这一步,然后跳转到别的页面
string strUserName = Request["txtLoginName"]; string strPwd = Request["txtPassword"]; //将用户的信息查询出来,放到 Session里面去 BLL.HKSJ_USERS userInfoService =new HKSJ_USERS(); Model.HKSJ_USERS user = userInfoService.GetLoginUserModel(strUserName, strPwd); if(user ==null) { //用户登录失败 Js = "<script>alert('用户名密码不正确')</script>";//推荐大家使用这种方式。来往前台传递js脚本 return; } //将用户的信息放到Session里面去 Session["loginUser"] = user;
this.Response.Redirect("AdminIndex.aspx");
大致的登陆就算是完成呢,当然还有些细节上的东西需要处理下的.
思考
如果我们是做后台管理之类当我们登陆后,后台页面肯定不止一个,那么我们是否要每次都要查询是否有sesiion了?如果每次这么做,那么会是有多么麻烦呢!
有一种解决的办法,我们可以定义一个basepage类,让它继承page,然后子页面再继承basepage,我们把对session的校验的事大可以放到基类的方法里面来做,具体怎么做了,首先需要一个basepage类
public class BasePage :System.Web.UI.Page//页面基类 { protected Model.HKSJ_USERS CurrentLoginUser { get; set; } //虚方法,允许子类重写此方法 protected virtual void Page_PreInit(object sender, EventArgs e) { CurrentLoginUser = (Model.HKSJ_USERS)Session["loginUser"]; if (CurrentLoginUser != null)//如果用户已经登录,那么Session里面就存放着用户登录的信息 { //this.Response.Write(currentLoginUserInfo.ID + currentLoginUserInfo.LoginName); } else// { this.Response.Redirect("~/公司网站/后台管理/Login.aspx"); } } }
然后我们在子类当中就可以重写方法,先调用父类方法,然后再写自己独有的.所谓的don't repeat yourself,不重复自己.
cookie跟session帮我们保持状态做了不少的贡献,他们各自有各自的特点跟使用场景,我们应该好好利用他们来帮我们解决一些状态保持的问题,当然还有viewstate application类 等也能帮我们保持状态,今天就说这两个了~ 我是个asp.net初学者,有些地方写的不好,望见谅,希望能够共同学习,共同进步~