当我们想在前台页面中做一个记住我的登录功能时,我们会想到两种方法去进行思考。
有时我们想要把用户信息放到客户端上会不会存在安全隐患,这样我们把信息放到服务器端有什么方法可以实现呢?那就只有session才能做到了。
也就是说存放信息有两种方式,一种是存在客户端,另一种就是存在服务器端。
我们先用排除法看看是否两种方法都可以在记住我这个功能上使用。
session:保存在服务器端。
当我们在登录页面中点击记住我,进行登录时,客户端和服务器端是通过http协议进行通讯,在服务器端会给我们注册一个session值,同时服务器端通过http协议向客户端输出一个sessionId,这样我们可以通过sessionid去实现记住我这个功能。但是在细想,session的值就算我们解决了过期时间,但他是和客户端的临时cooke配合着使用,存放在客户端的sessionid只是存在了浏览器当前应用程序中,一旦我们关闭了浏览器,该应用程序所占的内存即立即释放,也就是说sessionid丢失。下次在打开浏览器时,将得不到上一次sessionid的值,那么这样就不用在往下想怎样通过用户名及密码实现记住我的功能。
cooke:保存在客户端:
临时cookie:
持久cookie
临时cooke和持久cooke的区别就是设置一个过期时间,当不设置的时候,称为临时cooke,设置过期时间cooke即将保存在硬盘中:
通过cooke我想到了两种方法去实现他
第一种:
在用户表中加一个字段叫akey,当要写cookie时,生成一个guid(即不会重复,又让用户猜不到别人的akey),把这个guid写入用户的cookie中.
下次用户再来时,我们只检测有没有这个cookie,则证明以前有没有点击记住我过.我们就把guid的值读出来,然后在数据库中找到是谁的.把用户读进实体类,然后赋给Session["currUser"]
第二种:
把用户名和密码写入cookie
用户密码:p
随机产生一个两位的字符:s
加密算法: result = s+md5(s+md5(p))
登录记住我具体实现
//登录做测试的页面检查是否有点击记住我完成自动登录
public partial class test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Session["currUser"] != null)
{
//说明已登录
Model.User currUser = (Model.User)Session["currUser"];
Label1.Text = string.Format("你好,{0}!你的角色是:{1}", currUser.LoginId, currUser.UserRole.Name);
}
else
{
//未登录
Response.Redirect("login.aspx?return="+Request.Url.ToString());//返回登录页面,带的参数?return="+Request.Url.ToString()是为了记住上一次的url路径实现登录成功后自动跳转回当前页,跳转过去的页面只需要Request.QueryString["return"]就可取出上一个页面路径
}
}
protected void Button1_Click(object sender, EventArgs e)
{
Response.Cookies["user"].Expires = DateTime.Now.AddDays(-1);
Response.Cookies["pwd"].Expires = DateTime.Now.AddDays(-1);
Session.Abandon();
Response.Redirect("~/member/login.aspx");//退出登录,可以导回一个不用登录的页面,如首页
}
}
}
在用户控件中做登录控件
public partial class UsLogin : System.Web.UI.UserControl
{
UserManager userManager = new UserManager();//
protected void Page_Load(object sender, EventArgs e)
{
if (Request.Cookies["user"] != null && Request.Cookies["pwd"] != null)//检查客户端请求时是否存在cooke的用户名和密码
{
string cUser = Request.Cookies["user"].Value;
string cPwd = Request.Cookies["pwd"].Value;
Model.User loginUser = userManager.GetModel(cUser);//去数据库检查是否存在该用户
if (loginUser != null)//如果为空,说明网站上已经没有该用户了.可能被删掉了
{
string sysPwd = this.Encrypt(loginUser.LoginPwd, cPwd.Substring(0, 2));//调用加密算法
if (sysPwd == cPwd)
{
//验证cookie中存的密码是正确的
// 程序到这里,即验证用户的合法性,也验证了密码的合法性
Session["currUser"] = loginUser;
//把用户导向相应的网站.
// Common.ScriptWrite(Page, "window.location='test.aspx'");
this.GoPage();
}
else//如果上面的不执行就设置请求过来的cooke值过期,因为不能操作客户端因此remove方法是没用的
{
Response.Cookies["user"].Expires = DateTime.Now.AddDays(-1);
Response.Cookies["pwd"].Expires = DateTime.Now.AddDays(-1);
}
}
}
}
protected void btnLogin_Click(object sender, ImageClickEventArgs e)
{
if (!Page.IsValid)
return;
string loginId = txtLoginId.Text.Trim();
string pwd = Common.Md5Computer(txtLoginPwd.Text.Trim());
Model.User loginUser = new BookShop.Model.User();
try
{
if (userManager.CheckUserLogin(loginId, pwd, out loginUser))
{
if (cbAutoLogin.Checked)
{
//用户选中了记住我
//加密用户的密码
string strEncryptPwd = this.Encrypt(loginUser.LoginPwd);
HttpCookie cuser = new HttpCookie("user", loginUser.LoginId);
HttpCookie cpass = new HttpCookie("pwd", strEncryptPwd);
cuser.Expires = DateTime.Now.AddYears(10);
cpass.Expires = DateTime.Now.AddYears(10);
Response.Cookies.Add(cuser);
Response.Cookies.Add(cpass);
}
//返回值为true,验证成功!
Session["currUser"] = loginUser;
Common.ShowMessage(Page, "登录成功!");
// Common.ScriptWrite(Page, "window.location='test.aspx'");
this.GoPage();
}
else
{
Common.ShowMessage(Page, "登录失败!");
//验证失败
}
}
catch (Exception ex)
{
Common.ShowMessage(Page, "登录时意外错误!" + ex.Message);
}
}
protected void btnRegister_Click(object sender, ImageClickEventArgs e)
{
// Response.Redirect("~/member/Register.aspx");
Common.ScriptWrite(Page, "window.location='/member/register.aspx'");
}
protected string Encrypt(string txt,string key)
{
// 用户密码:p//随机产生一个两位的字符:s//加密算法: result = s+md5(s+md5(p))
string sult = "";
if (key.Length == 0)
{
Random r = new Random();
sult = ((char)r.Next(65, 91)).ToString() + ((char)r.Next(65, 91)).ToString();
}
else
{
sult = key;
}
string result =sult+ Common.Md5Computer(sult + Common.Md5Computer(txt));
return result;
}
protected string Encrypt(string txt)
{
return this.Encrypt(txt, "");
}
protected void GoPage()
{
if (Request.QueryString["return"] != null)
{
string returnUrl = Request.QueryString["return"];
//Response.Redirect(returnUrl); //由于前面有可能向前端输出了js代码,要执行,如alert,所以这里不要用Redirect
Common.ScriptWrite(Page,"window.location='"+returnUrl+"'");
}
else
{
//ResolveClientUrl("~/default.aspx");
Common.ScriptWrite(Page, "window.location='/default.aspx'");
}
}
}
//公共代码
public class Common
{
public static void ShowMessage(System.Web.UI.Page page, string msg)
{
msg = msg.Replace("\"", "");
msg = msg.Replace("'", "");
msg = msg.Replace("\r", "");
msg = msg.Replace("\n", "");
//第1:对msg的内容要进行过滤特殊字符,如:" ' \r \n
//第2:page.ClientScript.RegisterClientScriptBlock向前端输入脚本,后面一定要加一个;
page.ClientScript.RegisterClientScriptBlock(page.GetType(), Guid.NewGuid().ToString(),
"alert('"+msg+"');", true);
}
public static void ScriptWrite(System.Web.UI.Page page, string script)
{
page.ClientScript.RegisterClientScriptBlock(page.GetType(), Guid.NewGuid().ToString(),
script, true);
}
public static string Md5Computer(string str)
{
MD5 md5 = MD5.Create();
//字符串转byte[]
byte[] bytes= System.Text.Encoding.UTF8.GetBytes(str);
byte[] computeBytes= md5.ComputeHash(bytes);
string result = "";
for (int i = 0; i < computeBytes.Length; i++)
{
result+= computeBytes[i].ToString("X").Length == 1 ? "0" + computeBytes[i].ToString("X") : computeBytes[i].ToString("X");
}
return result;
}
}
}