asp.net 使用母版页自定义用户身份验证

asp.net custom user authentication with master page

我正在开发一个小型库存管理系统。我几乎已经在我的本地机器上创建了它。它按设计工作。我刚把它移到我的主机帐户,现在我遇到了一些问题。

1、登录后,当用户转到不同的页面时,打开和关闭表单,一段时间后重定向到登录页面。我不知道为什么。似乎发生了某种异常或会话为空。如何处理这种情况?

2,这是使用母版页的 Page_Load 事件检查用户登录的正确方法吗?

我的网站使用母版页,顶部导航菜单和底部正文区域具有单独的布局。当用户第一次登陆网站时,它会登录系统,成功登录后,我会将他的信息存储在会话中。为了添加、删除、更新目的,我在所有页面中大量使用 Session。执行添加记录时,我在会话中传递成功或失败消息以在 post 后显示。登录页面隐藏代码如下:

    protected void loginForm_OnAuthenticate(object sender, AuthenticateEventArgs e)
    {
        string error = "";
        sMethodName = "loginForm_OnAuthenticate";

        _objLoginBLL = new LoginBLL();

        int iRetVal = _objLoginBLL.ValidateUser(loginForm.UserName, loginForm.Password, ref error);

        if (iRetVal >= 0)
        {
            Session.Clear();        //Remove all stored Session variables.

            Session[Constant.Session.LOGGED_IN_DATETIME] = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            Session[Constant.Session.LOGIN_USERNAME] = loginForm.UserName;
            Session[Constant.Session.LOGIN_USER_ID] = iRetVal;
            Session[Constant.Session.LOGIN_COMPANY] = ddlCompanies.SelectedValue;
            Session[Constant.Session.LOGIN_FISCAL_YEAR] = ddlFiscalYear.SelectedValue;
            Session[Constant.Session.IS_DIRECT_ACCESS] = "NO";
            FormsAuthentication.RedirectFromLoginPage(loginForm.UserName, loginForm.RememberMeSet);
        }
        else
        {
            Logger.Log("User validation failed.", sClassName, sMethodName, DEBUG);

            switch (iRetVal)
            {
                case -1:
                    loginForm.FailureText = Constant.Messages.INCORRECT_USER_OR_PASSWORD;
                    loginForm.Focus();
                    break;

                case -2:
                    loginForm.FailureText = Constant.Messages.ACCOUNT_LOCKED;
                    loginForm.Focus();
                    break;

                //case -3: 
                    //TODO: Account doesn't exists

                default:
                    var randToken = new Random().Next(1000);
                    Session[Constant.Session.TOKEN] = randToken;
                    var myHashtable = new Hashtable
                    {
                        {Constant.Session.TOKEN, randToken},
                        {Constant.Fields.ERROR_KEY, iRetVal}
                    };

                    Response.Redirect(WebFunctions.CreateQueryString(Constant.Urls.Error, myHashtable));
                    break;
            }
        }
    }

我一直在检查会话是否不包含任何用户 ID,然后将其重定向到登录页面。我的母版页背后的代码如下:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (Session[Constant.Session.LOGIN_USER_ID] == null)
        {
            FormsAuthentication.RedirectToLoginPage();
            return;
        }

        CheckDBConnection();
        Initialize();
    }

如有任何帮助或提示,我们将不胜感激。

您可以在此处查看该站点:www.paracha.net(如果有人感兴趣,我可以在私人消息中分享来宾帐户凭据)

如果您使用 FormsAuthentication,则无需手动检查 Session[Constant.Session.LOGIN_USER_ID]。它将自动重定向到登录页面,您可以在 web.config.

中配置

另一个想法

与你的问题没有直接关系。这只是一种替代方法。

您可以创建自定义上下文来跟踪当前登录用户的信息,而不是创建多个会话状态

例如您可以将 Company 和 Fiscal Year 属性存储在 MyUser class.

void Application_AuthenticateRequest(object sender, EventArgs e)
{
    if (HttpContext.Current.User != null && 
        HttpContext.Current.User.Identity.IsAuthenticated)
    {
        MyContext.Current.MyUser = 
         YOUR_BLL.GetUserByUsername(HttpContext.Current.User.Identity.Name);
    }
}

public class MyContext
{
    private MyUser _myUser;

    public static MyContext Current
    {
        get
        {
            if (HttpContext.Current.Items["MyContext"] == null)
            {
                MyContext context = new MyContext();
                HttpContext.Current.Items.Add("MyContext", context);
                return context;
            }
            return (MyContext) HttpContext.Current.Items["MyContext"];
        }
        }

        public MyUser MyUser
        {

            get { return _myUser; }
            set { _myUser = value; }
        }
    }
}

加法

C#是强类型语言,所以你不应该用变量的类型来编码变量名。例如。 objLoginBLL 和 iRetVal。请阅读 C# 设计指南或 Essential C# 6.0 (Page 7).

首先,请记住会话 cookie 未加密,因此您不应使用会话来存储任何机密信息。

其次,您不应该在每个 Page_Load 上检查身份验证。相反,您应该在 web.config:

中配置页面访问
<configuration>
   <system.web>
      <authorization>
         <deny users="?"/>
      </authorization>
   </system.web>
</configuration>

这将保护您的所有页面,因此只有经过身份验证(即登录)的用户才能看到该页面,而所有其他用户将被重定向到登录页面。

如果您希望所有用户都可以访问某些页面(例如启动页面)或文件夹(例如图像文件夹),请为每个页面或文件夹添加一个部分:

<configuration>
  <location path="splash.aspx">
    <system.web>
      <authorization>
        <allow users="*"/>
      </authorization>
    </system.web>
  </location>
  <location path="images">
    <system.web>
      <authorization>
        <allow users="*"/>
      </authorization>
    </system.web>
  </location>
</configuration>

为了使其正常工作,您应该使用表单身份验证。下面是web.config中的设置:

<configuration>
  <system.web>
    <authentication mode="Forms">
      <forms
         name=".YOURNAME_AUTH"
         loginUrl="login"
         defaultUrl="/"
         protection="All"
         timeout="30"
         path="/"
         requireSSL="true"
         slidingExpiration="true"
         cookieless="UseCookies"
         domain=""
         enableCrossAppRedirects="false">
      </forms>
    </authentication>
   </system.web>
</configuration>

显然,你需要一个login.aspx页面,当你点击登录按钮时,你需要像这样验证用户:

protected void btnLogIn_Click(object sender, EventArgs e) {
  string Username = txtUsername.Text;
  string Password = txtPassword.Text;
  try {
    if (ValidateUser(Username, Password)) {
        FormsAuthentication.RedirectFromLoginPage(Username, false);
    }
    else {
        lblMessage.Text = "Incorrect Credentials.";
        lblMessage.ForeColor = Color.Red;
    }
  }
  catch {
    lblMessage.Text = "Login Failed.";
    lblMessage.ForeColor = Color.Red;
  }
}

函数ValidateUser()可以做任何你想做的事情来进行身份验证。如果愿意,您可以根据数据库验证凭据。