1,http协议是无状态的。服务器不会记住上次给浏览器的处理结果,如果需要上次处理结果(上次状态)就需要浏览器把处理结果值(上次状态)再次给服务器。
2,url传值:通过url参数或者通过form表单进行页面件的传值 (不能做到很自由的存取和读取,而且不安全)
3,cookie :①cookie可以用来进行更加自由的数据的存取和读取。
②cookie是和站点相关的,自己域名写的只有自己的域名才可以读取。
③客户端向服务器发送请求的时候 处理发送form表单信息以外还会把和站点有关的所有的cookie发送给服务器,是强制的。
④服务器返回的数据处理html数据以外,还会返回修改的cookie,浏览器拿到修改后的cookie更新到本地的cookie
⑤服务器端使用cookie案例,记住用户名功能:
a,设置页面值: response.setcookie(new httpcookie("username",username))
b,读取页面值: username=request.cookies["username"].value
⑥浏览器关闭以后cookie的声明周期到期,也就是cookie的默认生命周期是浏览器的生命周期。可以通过设置expires属性设置cookie的过期时间:cookie.expires=datetime.now.adddays(-1)
⑦cookie在客户端是以键值对存在的
4,cookie缺点:①客户端额可以手动清楚cookie 所以cookie里面存放的信息是可有可无的信息
②浏览器对 cookie 的大小有限制,因此只有不超过 4096 字节才能保证被接受
③机密信息不能放到cookie里面
④cookie不能跨浏览器
5,cookie的写和读: a,新建cookietest.html页面并添加 两个按钮分别用于cookie的读和写
代码如下:
<!doctype html>
<html xm lns="http://www.w3.org/1999/xhtml">
<head>
<me ta http-equiv="content-type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<form>
<in put type="submit" name="read" value="读取cookie" />
<in put type="submit" name="write" value="写入cookie" />
<br />
读取出来的cookie: $model.cookievalue
</form>
</body>
</html>
b,建立对应的cookietest.ashx页面 实现cookie的新建写入本地以及读取cookie的值
using system;
using system.collections.generic;
using system.linq;
using system.web;
namespace httpnostatus
{
/// <summary>
/// httpcookie 的摘要说明
/// </summary>
public class cookietest : ihttphandler
{
public void processrequest(httpcontext context)
{
context.response.contenttype = "text/html";
//if else 判断是点击的那个按钮
if (!string.isnullorempty(context.request["read"]))
{
if (context.request.cookies["age"] != null)
{
httpcookie cookie = context.request.cookies["age"];
string strvalue = cookie.value;
var data = new { cookievalue = strvalue };
//加载模板页面并传递 cookie value的值
string strhtml = common_nvelocity.renderhtml("cookietest.html", data);
context.response.write(strhtml);
}
else
{
context.response.write("cookie 不存在");
}
}
else if (!string.isnullorempty(context.request["write"]))
{
//写入新的cookie
httpcookie acookie = new httpcookie("age");
acookie.value = "25";
acookie.expires = datetime.maxvalue;
context.response.cookies.add(acookie);
//cookie不存在 直接加载模板页面
string strhtml = common_nvelocity.renderhtml("cookietest.html", null);
context.response.write(strhtml);
}
else
{
//第一次加载页面
string strhtml = common_nvelocity.renderhtml("cookietest.html", null);
context.response.write(strhtml);
}
}
public bool isreusable
{
get
{
return false;
}
}
}
}
6,cookie最主要的一个功能是保存用户的登陆名,这样用户在下次登陆的时候系统就可以自动填写登陆名称
a,新建logincookie.html页面,页面中添加我们经常见到的 用户名,用户密码,登陆
登陆页面第一次加载的时候,设置默认的登陆名为空,登陆成功以及再次登陆的时候系统就自动补充登陆用户名
<!doctype html>
<html xm lns="http://www.w3.org/1999/xhtml">
<head>
<me ta http-equiv="content-type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<form action="logincookie.ashx" method="post">
<table>
<tr>
<td>登陆名</td>
<td>
<in put type="text" name="username" value="$model.loginuser" /></td>
</tr>
<tr>
<td>密码</td>
<td>
<in put type="password" name="password" /></td>
</tr>
<tr>
<td>
<in put type="submit" name="login" value="登陆" /></td>
<td></td>
</tr>
</table>
</form>
</body>
</html>
b, 新建对应的logincookie.ashx页面,实现把用户名读取出来并写入cookie "ckloginuser"
using system;
using system.collections.generic;
using system.linq;
using system.web;
namespace httpnostatus
{
/// <summary>
/// logincookie 的摘要说明
/// </summary>
public class logincookie : ihttphandler
{
public void processrequest(httpcontext context)
{
context.response.contenttype = "text/html";
//加载页面直接显示 页面
if (context.request.form["login"] == null)
{
string strhtml = "";
var data = new { loginuser = "" }; //登陆账号默认为空
//判断cookie是否存在,如果存在 把cookie的值传递到html页面,如果不存在就是默认的空
if (context.request.cookies["ckloginuser"] != null)
{
data = new { loginuser = context.request.cookies["ckloginuser"].value.tostring() };
}
strhtml = common_nvelocity.renderhtml("logincookie.html", data);
context.response.write(strhtml);
}
else
{
//用户登陆,保存用户名到cookie
httpcookie loginuser = new httpcookie("ckloginuser");
loginuser.value = context.request.form["username"];
loginuser.expires = datetime.now.adddays(30);
context.response.cookies.add(loginuser);
//加载页面直接显示 页面
string strhtml = common_nvelocity.renderhtml("logincookie.html", new { loginuser = context.request.form["username"] });
context.response.write(strhtml);
}
}
public bool isreusable
{
get
{
return false;
}
}
}
}
7,以上方法把登陆账号以cookie的形式存放在客户端,这样每一次的请求就可以带出用户登陆名称了
有一种情况: 用户登陆成功以后就可以访问网站的其他所有页面,其他页面就需要先判断用户是否登陆成功。
如果登陆成功为true放到cookie中,这样的客户端就可以进行篡改把false改为true从而可以非法访问为授权页面了,这样放到cookie就不安全了。
如果登陆成功放到服务器端,那么网站的多个页面就可以直接读取到这个值,而且是安全的不会被客户端篡改的了。
8,session原理: 把数据value值存储在服务器端并在客户端存放value对应的id 。(id,value)都存放服务器 另外把id以cookie的形式存放客户端。这样就可以从客户端cookie中抓取id,然后从服务器端读取到id对应的value。
10,下面示例以session原理实现页面判断用户是否有成功登陆:成功登陆的用户可以对特定页面进行访问、如果没有成功登陆就跳转到登陆页面。
a. 添加类 sessionmgr.cs 在服务器端存储 键值对 id/value
using system;
using system.collections.generic;
using system.linq;
using system.web;
namespace httpnostatus
{
public class sessionmgr
{
//定义键值对,存储登陆信息
private static dictionary<guid, string> keyvalue = new dictionary<guid, string>();
//设置键值对的值
public static void setkeyvalue(guid id, string value)
{
keyvalue[id] = value;
}
/// <summary>
/// 检查客户端传递过来的键值对是否存在
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public static bool ifidexist(guid id)
{
return keyvalue.keys.contains(id);
}
//返回服务器端id对应的value值
public static string getvalue(guid id)
{
return keyvalue[id].tostring();
}
}
}
b. 添加 loginsession.ashx 判断用户是否登陆成功,如果登陆成功把存储对应的键值对的值
using system;
using system.collections.generic;
using system.linq;
using system.web;
namespace httpnostatus
{
/// <summary>
/// loginsession 的摘要说明
/// </summary>
public class loginsession : ihttphandler
{
public void processrequest(httpcontext context)
{
context.response.contenttype = "text/html";
string strhtml = "";
//读取用户名和密码
string strusername = context.request.form["txtusername"];
string strpwd = context.request.form["txtpassword"];
if (strpwd == "123456")
{
//登陆成功,设置对应的键值对
guid id = guid.newguid(); // 产生唯一的id
sessionmgr.setkeyvalue(id, strusername);
//id 保存在客户端cookie中
httpcookie logincookie = new httpcookie("logincookie");
logincookie.value = id.tostring();
logincookie.expires = datetime.now.adddays(7);
context.response.cookies.add(logincookie);
//跳转到授权页面
context.response.redirect("authorizationpage.ashx");
}
else
{
//登陆失败 , 加载登陆页面
strhtml = common_nvelocity.renderhtml("loginsession.html", null);
context.response.write(strhtml);
}
}
public bool isreusable
{
get
{
return false;
}
}
}
}
c. templates文件夹下添加loginsession.html 登陆页面
<!doctype html>
<html xm lns="http://www.w3.org/1999/xhtml">
<head>
<me ta http-equiv="content-type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<form action="loginsession.ashx" method="post">
<table>
<tr>
<td>登陆名</td>
<td>
<in put type="text" name="txtusername" /></td>
</tr>
<tr>
<td>密码</td>
<td>
<in put type="password" name="txtpassword" /></td>
</tr>
<tr>
<td>
<in put type="submit" name="login" value="登陆" /></td>
<td></td>
</tr>
</table>
</form>
</body>
</html>
d. 添加authorizationpage.ashx页面,只有登陆后的账户才有权限访问这个页面
using system;
using system.collections.generic;
using system.linq;
using system.web;
namespace httpnostatus.templates
{
/// <summary>
/// authorizationpage 的摘要说明
/// </summary>
public class authorizationpage : ihttphandler
{
public void processrequest(httpcontext context)
{
context.response.contenttype = "text/html";
//抓取客户端 cookie的id值
httpcookie logincookie = context.request.cookies["logincookie"];
if (logincookie != null)
{
guid id = new guid(logincookie.value);
// 读取id对应的value
string strvalue = sessionmgr.getvalue(id);
//输出value值,并提示该账号是已经登陆的账号
context.response.write(strvalue + ",您已经登陆本网站,有权限访问此页面");
}
//如果cookie不存在,则直接跳转到登页面
else
{
context.response.redirect("loginsession.ashx");
}
}
public bool isreusable
{
get
{
return false;
}
}
}
}
------------------------------------------------------------gif 动画演示----------------------------------------------------------------
11,上面的示例是也就是session原理。asp.net已经内置了session机制,下面我们直接用asp.net session实现 判断用户是否有登陆成功:
(一般处理程序httphandler操作session, 要实现irequiressessionstate接口)
分别添加页面: loginsessionnew.ashx(登陆一般处理程序) , loginsessionnew.html(登陆模板), authorizationpagenew.ashx(登陆后才有权限访问的页面)。
a,loginsessionnew.ashx(登陆一般处理程序)
using system;
using system.collections.generic;
using system.linq;
using system.web;
using system.web.sessionstate;
namespace httpnostatus
{
/// <summary>
/// loginsessionnew 的摘要说明
/// </summary>
public class loginsessionnew : ihttphandler, irequiressessionstate
{
public void processrequest(httpcontext context)
{
context.response.contenttype = "text/html";
string strhtml = "";
//读取用户名和密码
string strusername = context.request.form["txtusername"];
string strpwd = context.request.form["txtpassword"];
if (strpwd == "123456")
{
//登陆成功,直接保存session值
context.session["loginusername"] = strusername;
//跳转到授权页面
context.response.redirect("authorizationpagenew.ashx");
}
else
{
//登陆失败 , 加载登陆页面
strhtml = common_nvelocity.renderhtml("loginsessionnew.html", null);
context.response.write(strhtml);
}
}
public bool isreusable
{
get
{
return false;
}
}
}
}
b,templates模板下新建loginsessionnew.html(登陆模板)
<!doctype html>
<html xm lns="http://www.w3.org/1999/xhtml">
<head>
<me ta http-equiv="content-type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<form action="loginsessionnew.ashx" method="post">
<table>
<tr>
<td>登陆名</td>
<td>
<in put type="text" name="txtusername" /></td>
</tr>
<tr>
<td>密码</td>
<td>
<in put type="password" name="txtpassword" /></td>
</tr>
<tr>
<td>
<in put type="submit" name="login" value="登陆" /></td>
<td></td>
</tr>
</table>
</form>
</body>
</html>
c,authorizationpagenew.ashx(登陆后才有权限访问的页面)
using system;
using system.collections.generic;
using system.linq;
using system.web;
using system.web.sessionstate;
namespace httpnostatus
{
/// <summary>
/// authorizationpagenew 的摘要说明
/// </summary>
public class authorizationpagenew : ihttphandler, irequiressessionstate
{
public void processrequest(httpcontext context)
{
context.response.contenttype = "text/plain";
//检查session是否存在
ob ject obj = context.session["loginusername"];
if (obj != null)
{
//session存在,读取session值,并提示该账号是已经登陆的账号
context.response.write(obj.tostring() + ",您已经登陆本网站,有权限访问此页面");
}
//如果session不存在,则直接跳转到登页面
else
{
context.response.redirect("loginsessionnew.ashx");
}
}
public bool isreusable
{
get
{
return false;
}
}
}
}
· asp.net内置session机制同样实现了对用户是否登陆成功的判断:loginsessionnew.ashx页面headers中我们看到了cookie中多了asp.net_sessionid
session机制在客户端存放了asp.net_sessionid
· 权限访问页面,请求头中读取到了客户端cookie中的asp.net_sessionid
12, asp.net的session机制: session依赖于cookie , 借助cookie在客户端浏览器中记录了id, 在服务器端存储了value值。
13,session的值是放到了服务器内存中,所以session存放小数据。
session(会话)有自动销毁机制,如果一段时间内浏览器没有和服务器交互,则session会定时自动销毁。
登陆账号后,一段时间内如果不操作 系统就会自动退出,这就是session自动销毁了。
更多信息请查看IT技术专栏