首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ASP.NET AJAX 登入系統完整實作:記住帳號、MD5 加密、無刷新體驗

     編輯:ASP.NET 基礎

功能需求

  • 母版頁內嵌登入區塊
  • AJAX 無刷新登入/登出
  • 「記住帳號」/「記住密碼」勾選
  • 密碼以機器相關鹽值 MD5 加密存 Cookie
  • 二次訪問自動驗證 Cookie 免登入

前台母版頁關鍵邏輯

<script src="jquery-1.7.1.min.js"></script>
<script>
function CheckLoginState() {
    $.post("Member/Data/GetMemberInfo.ashx?method=CheckLoginStatus", function(data) {
        var json = $.parseJSON(data);
        if (json.Status && json.UserName) {
            // 已登入:隱藏登入框,顯示歡迎區
            $("#divNotLogin").hide(); $("#divIsLogin").show();
            $("#liLogin").hide(); $("#liLogout").show();
            $("#lbUserName").text(json.UserName);
        } else if (json.Status && !json.UserName) {
            // 僅記住帳號
            $("#divNotLogin").show(); $("#divIsLogin").hide();
            $("#txtUserName").val(json.UserName);
        } else {
            // 未登入
            $("#divNotLogin").show(); $("#divIsLogin").hide();
        }
    });
}

$(function() {
    CheckLoginState(); // 頁面載入即檢查

    $("#aLogin").click(function() {
        var data = {
            Name: $("#txtUserName").val(),
            Pwd: $("#txtPwd").val(),
            cbName: $("#cbUserName").is(":checked") ? "1" : "0",
            cbPwd: $("#cbPwd").is(":checked") ? "1" : "0"
        };
        $.post("Member/Data/GetMemberInfo.ashx?method=MemberLogin", data, function(ret) {
            var json = $.parseJSON(ret);
            if (json.Status) {
                $("#divNotLogin").hide(); $("#divIsLogin").show();
                $("#liLogin").hide(); $("#liLogout").show();
                $("#lbUserName").text(json.UserName);
            } else {
                alert("帳號密碼錯誤或未信箱驗證!");
            }
        });
    });
});
</script>

後台 HttpHandler (GetMemberInfo.ashx)


public class GetMemberInfo : IHttpHandler, IRequiresSessionState
{
    public void ProcessRequest(HttpContext context)
    {
        string method = context.Request["method"];
        if (!string.IsNullOrEmpty(method)) CallMethod(method, context);
    }

    void CallMethod(string method, HttpContext context)
    {
        switch (method)
        {
            case "MemberLogin": MemberLogin(context); break;
            case "CheckLoginStatus": CheckLoginStatus(context); break;
            case "MemberLogout": MemberLogout(context); break;
            case "SaveMemberInfo": SaveMemberInfo(context); break;
            case "CheckExistUserName": CheckExistUserName(context); break;
        }
    }

    // 登入驗證
    void MemberLogin(HttpContext context)
    {
        string name = context.Request["Name"];
        string pwd = context.Request["Pwd"];
        string saveName = context.Request["cbName"];
        string savePwd = context.Request["cbPwd"];

        if (Tools.IsValidInput(ref name) && Tools.IsValidInput(ref pwd))
        {
            var info = new Member { Username = name, Password = pwd };
            bool ok = new MemberBLL().MemberLogin(info);
            string json = new MemberBLL().WriteJsonForLogin(ok, info.Username);
            if (ok)
            {
                new MemberBLL().RememberUserInfo(info, 
                    new MemberBLL().GetRememberType(saveName, savePwd));
                context.Session["UserName"] = info.Username;
            }
            context.Response.Write(json);
        }
    }

    // 自動登入檢查
    void CheckLoginStatus(HttpContext context)
    {
        string user = (string)context.Session["UserName"];
        if (!string.IsNullOrEmpty(user))
        {
            new MemberBLL().WriteJsonForLogin(true, user);
            return;
        }
        context.Response.Write(new MemberBLL().CheckLoginStatus());
    }

    // 登出
    void MemberLogout(HttpContext context)
    {
        context.Session.Remove("UserName");
        CookieHelper.ClearCookie("UserName");
        CookieHelper.ClearCookie("Pwd");
        JScript.AlertAndRedirect("安全登出!", "Default.aspx");
    }
    // ... 其他方法略
}

BLL 核心邏輯


public enum RememberType { RememberName, RememberNameAndPwd, NoRemember }

public RememberType GetRememberType(string saveName, string savePwd)
{
    if (saveName == "1" && savePwd == "1") return RememberType.RememberNameAndPwd;
    if (saveName == "1") return RememberType.RememberName;
    return RememberType.NoRemember;
}

public bool RememberUserInfo(Member info, RememberType type)
{
    if (type == RememberType.RememberName)
        CookieHelper.SetCookie("UserName", info.Username, DateTime.Now.AddDays(7));
    else if (type == RememberType.RememberNameAndPwd)
    {
        string md5 = Tools.GetMD5(info.Password); // 機器相關鹽值
        CookieHelper.SetCookie("UserName", info.Username, DateTime.Now.AddDays(7));
        CookieHelper.SetCookie("Pwd", md5, DateTime.Now.AddDays(7));
    }
    return true;
}

public string CheckLoginStatus()
{
    string user = CookieHelper.GetCookieValue("UserName");
    string pwd = CookieHelper.GetCookieValue("Pwd");
    if (string.IsNullOrEmpty(user) || string.IsNullOrEmpty(pwd))
        return WriteJsonForLogin(false, user);

    string realPwdHash = Tools.GetMD5(new MemberDAL().GetPassword(user));
    bool ok = realPwdHash == pwd;
    return WriteJsonForLogin(ok, user);
}

public string WriteJsonForLogin(bool status, string user)
{
    var sb = new StringBuilder();
    using (var sw = new StringWriter(sb))
    using (var jw = new JsonTextWriter(sw))
    {
        jw.WriteStartObject();
        jw.WritePropertyName("Status"); jw.WriteValue(status);
        jw.WritePropertyName("UserName"); jw.WriteValue(user);
        jw.WriteEndObject();
    }
    return sb.ToString();
}

安全性亮點

  1. 密碼不以明文存 Cookie,改存 MD5(密碼 + 機器鹽)
  2. 驗證時重新計算雜湊比對,Cookie 竊取也無法直接還原密碼
  3. SQL 參數化 + Tools.IsValidInput 防注入
  4. Session + Cookie 雙重驗證

效果圖

登入前後對比

自動登入效果

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved