欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

一步一步学asp.net Ajax登录设计实现解析

程序员文章站 2024-03-07 09:02:08
任务需求:做一个登录,拥有自动记住账号和密码的功能,要保证安全性,ajax,无刷新,良好的用户体验.(母板页) 这是前台页面,要求实现用户登录 首先我们分析, 用户需求:...
任务需求:做一个登录,拥有自动记住账号和密码的功能,要保证安全性,ajax,无刷新,良好的用户体验.(母板页)

这是前台页面,要求实现用户登录
一步一步学asp.net Ajax登录设计实现解析
首先我们分析,

用户需求:

1. 登录以后,登录框隐藏,并且欢迎登录的框显示,并且,左上角登录的按钮消失,安全退出显示.

2. 如果选择记住帐号和密码,下次登录直接登录,并且保证安全性.

实现过程:

首先,登录的时候发出ajax请求,用户验证登录,登录以后,保存当前用户名和密码到cookies中,注意,密码要用md5加密,md5是根据用户的机器配置生成的,并且返回登录状态和用户名的json数据

第二次登录的时候,检测用户状态,如果用户cookies保存的用户名和密码,根据用户名读取用户密码,并进行md5加密,检验两次密码是否相同,如果相同就返回json数据,登录状态true和用户名,如果cookies中只有用户名,那么返回登录状态为false和用户名

前台主要代码:
复制代码 代码如下:

<%@ master language="c#" autoeventwireup="true" codefile="left_top_dwon.master.cs"
inherits="left_top_dwon" %>
<!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="head1" runat="server">
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<link href="css/top_foot.css" rel="stylesheet" type="text/css" />
<link href="css/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src='<%=resolveurl("js/main_nav.js")%>'></script>
<script type="text/javascript" src='<%=resolveurl("js/nav.js") %>'></script>
<script src='<%=resolveurl("admin/scripts/jquery-1.7.1.min.js")%> ' type="text/javascript"></script>
<script type="text/javascript">
//检测登录状态
function checkloginstate()
{
$.ajax({
url:"member/data/getmemberinfo.ashx?method=checkloginstatus",
type:"post",
success:function(data,status){
var jsoninfo= $.parsejson(data);
// alert(data);
//同时记住账号和密码
if(jsoninfo.status&&jsoninfo.username!="")
{
$("#divnotlogin").hide();
$("#divislogin").show();
$("#lilogin").hide();
$("#lilogout").show();
$("#lbusername").text(jsoninfo.username);
}
//如果只记住账号
else if(jsoninfo.status&&jsoninfo.username==""){
$("#divnotlogin").show();
$("#divislogin").hide();
$("#lilogin").show();
$("#lilogout").hide();
$("#txtusername").val(jsoninfo.username);
}
else{
$("#divnotlogin").show();
$("#divislogin").hide();
$("#lilogin").show();
$("#lilogout").hide();
}
}
});
}
$(function(){
//第一次登录需要检测是否自动登录
checkloginstate();
//获取新闻类别
$.ajax({
url:'<%=resolveurl("admin/news/data/getnewsinfo.ashx?method=getnewstypeforcombox")%>',
type:"get",
success:function(text){
var jsondata=$.parsejson(text);
$("#m2").empty();//先清空m2子元素的内容
$.each(jsondata,function(key,value){ //注意这里
//这里链接还需要添加具体页面
$("#m2").append('<a href=\"'+'<%=resolveurl("news/newslist.aspx?typeid=")%>'+value.typeid+'\">'+value.typename+'</a>');
});
}
});
//获取工艺知识类别
$.ajax({
url:'<%=resolveurl("admin/product/data/getproductinfo.ashx?method=gettopcrafttypeinfo")%>',
type:"get",
success:function(text){
var jsondata=$.parsejson(text);
$("#m1").empty();//先清空m2子元素的内容
$.each(jsondata,function(key,value){ //注意这里
//这里链接还需要添加具体页面
$("#m1").append('<a href=\"'+'<%=resolveurl("craftknowledge/craftknowledgelist.aspx?fid=")%>'+value.fid+'\">'+value.typename+'</a>');
});
}
});
//登录
$("#alogin").click(function(){
var name=$("#txtusername").val();
var pwd=$("#txtpwd").val();
var cbname=$("#cbusername").attr("checked");
var cbpwd=$("#cbpwd").attr("checked");
if(name==""||pwd=="")
{
alert("用户名或密码不能为空!");
return;
}
if(cbname=="checked")
cbname="1";
else
cbname="0";
if(cbpwd=="checked")
cbpwd="1";
else
cbpwd="0";
var data={"name":name,"pwd":pwd,"cbname":cbname,"cbpwd":cbpwd }
$.ajax({
url:"member/data/getmemberinfo.ashx?method=memberlogin",
type:"post",
data:data,
success:function(returndata,status){
var jsoninfo= $.parsejson(returndata);
if(jsoninfo.status)
{
$("#divnotlogin").hide();
$("#divislogin").show();
$("#lilogin").hide();
$("#lilogout").show();
$("#lbusername").text(jsoninfo.username);
}
else{
alert("您输入的帐号或密码错误!也有可能您的帐号未邮箱激活!");
}
}
});
});
});
</script>
<asp:contentplaceholder id="head" runat="server">
</asp:contentplaceholder>
</head>
<body>
<div class="sheel">
<div class="header">
<div class="top_side">
<ul>
<li id="lilogin"><a href="#">登录</a> | </li>
<li><a href="#">注册</a> </li>
<li>|<a href="#">个人信息</a> </li>
<li>|<a href="#">我的收藏夹</a> </li>
<li>|<a href="#">我的留言</a> </li>
<li>|<a href="#">总站留言</a> </li>
<li id="lilogout">|<a id="a2" href='<%=resolveurl("member/data/getmemberinfo.ashx?method=memberlogout")%>'>安全退出</a></li>
</ul>
</div>
<div class="nav">
<ul id="sddm">
<li><a href="#">首  页</a> </li>
<li><a href="#">工艺概况</a></li>
<li><a href="#" onmouseover="mopen('m1')" onmouseout="mclosetime()">工艺知识</a>
<div id="m1" onmouseover="mcancelclosetime()" onmouseout="mclosetime()">
<a href="#">大吴泥塑</a> <a href="#">金漆木雕</a> <a href="#">潮州刺绣</a> <a href="#">潮州陶瓷</a>
</div>
</li>
<li><a href="#">作品展览</a></li>
<li><a href="#">非遗作品</a></li>
<li><a href="#" onmouseover="mopen('m2')" onmouseout="mclosetime()">新闻中心</a>
<div id="m2" onmouseover="mcancelclosetime()" onmouseout="mclosetime()">
<a href="#">大吴泥塑</a> <a href="#">金漆木雕</a> <a href="#">潮州刺绣</a> <a href="#">潮州陶瓷</a>
</div>
</li>
<li><a href="#">大师风采</a></li>
<li><a href="#">企业展示</a></li>
<li><a href="#">联系我们</a></li>
</ul>
</div>
</div>
<div class="content">
<div class="left_side">
<form id="flogin">
<div class="logo_bottom">
</div>
<div class="login">
<h4>
用户登录</h4>
<div class="lg_table" id="divnotlogin">
<table class="table1" width="198" cellpadding="0" cellspacing="0" border="0">
<tr>
<td width="40" align="right">
用户名
</td>
<td width="108" align="center">
<input type="text" id="txtusername" name="txtusername" />
</td>
<td width="50" rowspan="2">
<a href="#" id="alogin">
<img src='<%=resolveurl("images/login.png")%>' alt="登录" /></a>
</td>
</tr>
<tr>
<td align="right">
密码
</td>
<td align="center">
<input type="password" name="txtpwd" id="txtpwd" />
</td>
</tr>
</table>
<div class="border">
</div>
<table class="table2" width="190" cellpadding="0" cellspacing="0" border="0">
<tr>
<td width="90">
<a href="#">
<img src='<%=resolveurl("images/lg_forget.png")%>' alt="忘记密码" /></a>
</td>
<td width="100">
<a href="#">
<img src='<%=resolveurl("images/zhuce.png")%>' alt="注册" /></a>
</td>
</tr>
<tr>
<td>
<input type="checkbox" name="cbusername" id="cbusername" /><span>记住用户名</span>
</td>
<td>
<input type="checkbox" name="cbpwd" id="cbpwd" /><span>记住密码</span>
</td>
</tr>
</table>
</div>
<div class="lg_table" id="divislogin">
<table id="tbislogin" class="table1" width="198" cellpadding="0" cellspacing="0"
border="0">
<tr>
<td class="style1" style="height: 90px">
<font style="color: red">欢迎您回来!</font><br />
        尊敬的的<font style="color: red"><label id="lbusername"></label></font>用户! 
</td>
</tr>
<tr>
<td align="center" class="style2">
<a href="###">查看个人信息</a>  | <a id="a1" href='<%=resolveurl("member/data/getmemberinfo.ashx?method=memberlogout")%>'>退出</a>
</td>
</tr>
</table>
</div>
</div>
</form>
<div class="enter enter1">
<a href="#">
<img src='<%=resolveurl("images/master.png")%>' alt="大师入口" title="大师入口" /></a></div>
<div class="enter enter2">
<a href="#">
<img src='<%=resolveurl("images/company.png")%>' alt="企业入口" title="企业入口" /></a></div>
<div class="paihang">
<h3>
<p class="hide">
推荐排行榜</p>
<p>
<a href="#">更多</a></p>
</h3>
<ul class="ph_ul" id="ph1">
<li><a href="#" onmouseover="setph(0);" class="ph_hover">大师推荐</a></li>
<li><a href="#" onmouseover="setph(1);">工艺品推荐</a></li>
<li><a href="#" onmouseover="setph(2);">企业推荐</a></li>
</ul>
<div class="ph_p" id="ph2">
<ul style="display: block;">
<li class="ph_li1"><a href="#" class="phplihover">周少君</a></li>
<li class="ph_li2"><a href="#">周少君</a></li>
<li class="ph_li3"><a href="#">周少君</a></li>
<li class="ph_li4"><a href="#">周少君</a></li>
<li class="ph_li5"><a href="#">周少君</a></li>
</ul>
<ul>
<li class="ph_li1"><a href="#" class="phplihover">大大个</a></li>
<li class="ph_li2"><a href="#">大大个</a></li>
<li class="ph_li3"><a href="#">大大个</a></li>
<li class="ph_li4"><a href="#">大大个</a></li>
<li class="ph_li5"><a href="#">大大个</a></li>
</ul>
<ul>
<li class="ph_li1"><a href="#" class="phplihover">小小粒</a></li>
<li class="ph_li2"><a href="#">小小粒</a></li>
<li class="ph_li3"><a href="#">小小粒</a></li>
<li class="ph_li4"><a href="#">小小粒</a></li>
<li class="ph_li5"><a href="#">小小粒</a></li>
</ul>
</div>
</div>
<div class="question">
<h3>
<p class="hide">
参与调查</p>
</h3>
<table width="200">
<tr>
<td colspan="2">
<b>q.</b><span>您最喜欢以下哪种工艺品?</span>
</td>
</tr>
<tr>
<td>
<input type="radio" /><span>泥塑</span>
</td>
<td>
<input type="radio" /><span>木雕</span>
</td>
</tr>
<tr>
<td>
<input type="radio" /><span>陶瓷</span>
</td>
<td>
<input type="radio" /><span>石雕</span>
</td>
</tr>
<tr>
<td>
<a href="#">
<img src='<%=resolveurl("images/sumbit.gif")%>' alt="提交" /></a>
</td>
<td>
<a href="#">
<img src='<%=resolveurl("images/see.gif")%>' alt="查看结果" /></a>
</td>
</tr>
</table>
</div>
<div class="search">
<div class="search_thing">
<table width="225">
<tr>
<td height="25">
<select name="select" class="select">
<option>木雕</option>
<option>泥塑</option>
<option>陶瓷</option>
</select>
</td>
<td height="25">
<input type="text" value="" />
</td>
</tr>
<tr>
<td colspan="2">
<a href="#">
<img src='<%=resolveurl("images/search.png")%>' alt="搜索" /></a>
</td>
</tr>
<tr>
<td colspan="2" class="high_search">
<a href="search.html">前往高级搜索>></a>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="right_side">
<asp:contentplaceholder id="contentplaceholder1" runat="server">
</asp:contentplaceholder>
</div>
<div class="footer">
<div class="s_nav">
<ul>
<li><a href="#">在线留言</a>|</li>
<li><a href="#">联系我们</a>|</li>
<li><a href="#">关于我们</a>|</li>
<li><a href="#">企业信息</a>|</li>
<li><a href="#">招商合作</a></li>
</ul>
</div>
<div class="foot">
<p>
<span>广东省潮州</span> <span>2011 © all rights reserved. [版权所有] 学生创新活动中心</span>
</p>
<p>
<span>制作与维护:计算机工程研发实验室</span><span>联系qq群:73983871</span></p>
</div>
</div>
</div>
</div>
</body>
</html>

接下来,后台相应请求:
复制代码 代码如下:

<%@ webhandler language="c#" class="getmemberinfo" %>
using system;
using system.web;
using common;
using czcraft.model;
using czcraft.bll;
using system.web.sessionstate;
public class getmemberinfo : ihttphandler, irequiressessionstate
{
// //记录日志
private static readonly log4net.ilog logger = log4net.logmanager.getlogger(system.reflection.methodbase.getcurrentmethod().declaringtype);
public void processrequest(httpcontext context)
{
string methodname = context.request["method"];
if (!string.isnullorempty(methodname))
callmethod(methodname, context);
}
/// <summary>
/// 根据业务需求调用不同的方法
/// </summary>
/// <param name="method">方法</param>
/// <param name="context">上下文</param>
public void callmethod(string method, httpcontext context)
{
switch (method)
{
case "checkexistusername":
checkexistusername(context);
break;
case "memberlogin":
memberlogin(context);
break;
case "savememberinfo":
savememberinfo(context);
break;
case "checkloginstatus":
checkloginstatus(context);
break;
case "memberlogout":
memberlogout(context);
break;
default:
return;
}
}
/// <summary>
/// 退出
/// </summary>
/// <param name="context"></param>
public void memberlogout(httpcontext context)
{
string username = (string)context.session["username"];
memberbll bll = new memberbll();
if (!tools.isnullorempty(username))
{
//如果session存在,清除session
context.session.remove("username");
}
//清除cookies
cookiehelper.clearcookie("username");
cookiehelper.clearcookie("pwd");
//页面跳转
jscript.alertandredirect("安全退出成功!欢迎下次前来访问!", "http://www.cnblogs.com/default.aspx");
}
/// <summary>
/// 检查用户登录状态
/// </summary>
/// <param name="context"></param>
public void checkloginstatus(httpcontext context)
{
string username = (string)context.session["username"];
memberbll bll = new memberbll();
if (!tools.isnullorempty(username))
{
//如果session存在,直接返回用户状态
bll.writejsonforlogin(true, username);
}
else
{
//用户自动登录状态检测
context.response.write(bll.checkloginstatus());
}
}
/// <summary>
/// 会员登录
/// </summary>
/// <param name="context"></param>
public void memberlogin(httpcontext context)
{
try
{
//获取数据
string name = context.request["name"];
string pwd = context.request["pwd"];
string issavename = context.request["cbname"];
string issavepwd = context.request["cbpwd"];
//用户登录状态
bool status = false;
//返回给客户端的json数据
string returnjson = "";
//sql注入检测
if (tools.isvalidinput(ref name, true) && (tools.isvalidinput(ref pwd, true)) && (tools.isvalidinput(ref issavename, true)) && (tools.isvalidinput(ref issavepwd, true)))
{
member info = new member();
memberbll bll = new memberbll();
info.username = name;
info.password = pwd;
returnjson = bll.returnjson(info, out status);
if (status) //如果成功登陆
{
//记住帐号和密码
bll.rememberuserinfo(info, bll.getremembertype(issavename, issavepwd));
//保存登录状态
context.session["username"] = info.username;
}
context.response.write(returnjson);
}
}
catch (exception ex)
{
logger.error("会员登录出错!", ex);
}
}
/// <summary>
/// 验证帐号是否存在
/// </summary>
/// <param name="context"></param>
public void checkexistusername(httpcontext context)
{
string username = context.request["username"];
if (tools.isvalidinput(ref username, true))
{
context.response.write(new memberbll().checkexistusername(username));
}
}
/// <summary>
/// 保存用户信息
/// </summary>
/// <param name="context"></param>
public void savememberinfo(httpcontext context)
{
try
{
//表单读取
string txtusername = context.request["txtusername"];
string txtpwd = context.request["txtpwd"];
string txtemail = context.request["txtemail"];
string txtcheckcode = context.request["txtcheckcode"];
//验证码校验
if (!txtcheckcode.equals(context.session["checkcode"].tostring()))
{
return;
}
//字符串sql注入检测
if (tools.isvalidinput(ref txtusername, true) && tools.isvalidinput(ref txtpwd, true) && tools.isvalidinput(ref txtemail, true))
{
member info = new member();
info.username = txtusername;
info.password = txtpwd;
info.email = txtemail;
info.states = "0";
if (new memberbll().addnew(info) > 0)
{
smtp smtp = new smtp(info.email);
string webpath = context.request.url.scheme + "://" + context.request.url.authority + "/default.aspx";
smtp.activation(webpath, info.username);//发送激活邮件
jscript.alertandredirect("注册用户成功!!", "../default.aspx");
}
else
{
jscript.alertandredirect("注册用户失败!", "../default.aspx");
}
}
}
catch (exception ex)
{
logger.error("错误!", ex);
}
}
public bool isreusable
{
get
{
return false;
}
}
}

业务逻辑bll部分代码:
复制代码 代码如下:

/// <summary>
/// 用户登录
/// </summary>
/// <param name="info">会员model</param>
/// <returns></returns>
public bool memberlogin(member info)
{
return new memberdal().memberlogin(info);
}
/// <summary>
/// 返回给客户端的json格式数据(用于根据用户登录状态决定)
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
public string returnjson(member info, out bool status)
{
//登录状态
status = memberlogin(info);
//生成json格式数据
return writejsonforlogin(status, info.username);
}
/// <summary>
/// 记住帐号和密码的枚举
/// </summary>
public enum remembertype
{
/// <summary>
/// 记住帐号
/// </summary>
remembername = 0,
/// <summary>
/// 同时记住帐号和密码
/// </summary>
remembernameandpwd = 1,
/// <summary>
/// 不记住帐号密码
/// </summary>
noremember = 2
}
/// <summary>
/// 根据保存帐号密码状态判断是保存帐号还是同时保存帐号和密码
/// </summary>
/// <param name="issavename">"1"代表保存,"0"代表不保存</param>
/// <param name="issavepwd">"1"代表保存,"0"代表不保存</param>
/// <returns></returns>
public remembertype getremembertype(string issavename, string issavepwd)
{
remembertype savetype = remembertype.noremember;
//保存帐号和密码
if (issavename.equals("1") && issavepwd.equals("1"))
{
savetype = remembertype.remembernameandpwd;
}
//保存帐号
if (issavename.equals("1") && !issavepwd.equals("1"))
{
savetype = remembertype.remembername;
}
else if(!issavename.equals("1"))
{
savetype = remembertype.noremember;
}
return savetype;
}
/// <summary>
/// 检查用户登录状态,用于验证自动登录(并返回json格式)
/// </summary>
/// <returns></returns>
public string checkloginstatus()
{
//登录状态
bool status = true;
string username = common.cookiehelper.getcookievalue("username");
//如果cookies为空,直接返回
if (tools.isnullorempty(username))
{
status = false;
}
string pwd = common.cookiehelper.getcookievalue("pwd");
if (tools.isnullorempty(pwd))
{
status = false;
}
else
{
//查找该用户真实密码,并进行md5加密
string password = tools.getmd5(new memberdal().getpassword(username));
//如果两次密码相同则可以自动登陆了
if (!password.equals(pwd))
{
status = false;
}
}
//生成json格式数据
return writejsonforlogin(status, username);
}
/// <summary>
/// 为用户登录写入json数据
/// </summary>
/// <param name="status">登录状态</param>
/// <param name="username">用户名</param>
/// <returns></returns>
public string writejsonforlogin(bool status, string username)
{
stringbuilder json = new stringbuilder();
stringwriter sw = new stringwriter(json);
using (jsonwriter jsonwriter = new jsontextwriter(sw))
{
jsonwriter.formatting = formatting.indented;
jsonwriter.writestartobject();
jsonwriter.writepropertyname("status");
jsonwriter.writevalue(status);
jsonwriter.writepropertyname("username");
jsonwriter.writevalue(username);
jsonwriter.writeendobject();
}
return json.tostring();
}
/// <summary>
/// 记住用户信息
/// </summary>
/// <param name="type">记住用户信息类别</param>
/// <returns></returns>
public bool rememberuserinfo(member info, remembertype type)
{
if (type == remembertype.remembername)
{
//记住帐号7天
cookiehelper.setcookie("username", info.username, datetime.now.adddays(7));
}
else if (type == remembertype.remembernameandpwd)
{
//md5哈希加密
string sercret = tools.getmd5(info.password);
//同时记住帐号和密码7天
cookiehelper.setcookie("username", info.username, datetime.now.adddays(7));
cookiehelper.setcookie("pwd", sercret, datetime.now.adddays(7));
}
else
{
return false;
}
return true;
}

实现效果:
一步一步学asp.net Ajax登录设计实现解析

总结:
我们天天都在写用户登录,但是考虑安全性,复用性,却是非常少的,在这次实践过程中,switch语句,还是一个大问题,至今除了反射没有太好的解决方法,正在考虑!
可以发现,这次的实现改进非常大,我清晰的记得去年实现这个功能的糟糕代码, 太垃圾了,代码凌乱呀……
代码重质量,总结分析学习!
一步一步学asp.net Ajax登录设计实现解析
作者 cnblogs tianzh