我创建了登录页面,我想验证用户是否有权访问。我完成了大部分工作,但这里只需要几件事: 1)如果用户被验证,那么我想重定向到Home.aspx页面 2)在验证用户之后,我希望能够在会话中保存用户ID,这样如果他们被重定向到另一个页面,他们就不必每次都登录。 基本上,一旦他们成功登录,他们应该能够导航应用程序中的其他页面。谢谢。 这是背后的代码:
protected void ValidateUser3(object sender, EventArgs e)
{
int userId = 0;
string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand("Validate_User"))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@Username", txtUID.Text.Trim());
cmd.Parameters.AddWithValue("@Password", txtPWD.Text.Trim());
cmd.Connection = con;
con.Open();
userId = Convert.ToInt32(cmd.ExecuteScalar());
con.Close();
}
switch (userId)
{
case -1:
logLbl.Text = "Username and/or password is incorrect.";
break;
case -2:
logLbl.Text = "Account has not been activated.";
break;
}
}
}
这是我的存储过程:
ALTER PROCEDURE [dbo].[Validate_User]
@Username NVARCHAR(20),
@Password NVARCHAR(20)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @UserId INT, @LastLoginDate DATETIME
SELECT @UserId = UserId, @LastLoginDate = LastLoginDate
FROM myTable WHERE Username = @Username AND [Password] = @Password
IF @UserId IS NOT NULL
BEGIN
IF NOT EXISTS(SELECT UserId FROM [Main].[UserActivation] WHERE UserId = @UserId)
BEGIN
UPDATE myTable.[dbo].[UserProfile]
SET LastLoginDate = GETDATE()
WHERE UserId = @UserId
SELECT @UserId [UserId] -- User Valid
END
ELSE
BEGIN
SELECT -2 -- User not activated.
END
END
ELSE
BEGIN
SELECT -1 -- User invalid.
END
END
答案 0 :(得分:1)
首先,我要考虑收紧这种安全性。不要在您的数据库中保存密码,甚至不要将密码保存在数据库中。并在评论中遵循krillgar的建议:)
您想要对每个用户帐户执行的操作是创建一个唯一的salt代码 - 一个随机值,长度至少为8(自然越多越好):See here for creating a salt code。您希望将其保存在users表的数据库中。因此,您将拥有类似于表结构的内容:UserId,UserName,PassString,SaltCode,Active
选择哈希方法; MD5
或SHA1
是典型的例子。创建密码后,您将获取用户名,将其合并到密码中,添加您的盐码然后哈希。这将创建一个唯一的字符串 - 这是您在PassString字段中保存到数据库中的字符串。
因此,当有人登录时,请使用用户名和密码,查找用户记录,获取salt代码。将它们全部哈希,然后比较两个哈希字符串。
请查看Stack Overflow上的此部分:How to hash a password
这使得您的密码不可逆转,换句话说没有所有数据段;用户输入登录的密码是拼图的缺失键。如果某人能够以某种方式从您的表格中获取数据,那么他们将需要大量工作来破解用户的帐户。
所以现在回答你的实际问题:)
就像您使用存储过程一样,当用户成功匹配时返回一个值,例如1.我建议您将返回代码和用户ID值分开,这样代码中的模糊性就会降低。您可以选择使用SP,您可以使用Select语句(即Select 1, @UserId
)返回用户ID和返回代码,也可以使用OUTPUT
参数,这里是一个相当不错的示例:Using stored procedure output parameters in C#(我赞成后者)。
正在使用您已经拥有的内容(我的意思是,不是告诉您使用System.IdentityModel.Service
,UserPrinciple
等等...
一旦您的SP确认了成功登录,请按以下方式使用会话变量,会话变量保留在服务器端,因此除非您的服务器受到损害,否则您将没事:
Session["UserId"] = userId;
Response.Redirect("Home.aspx");
现在在像Home.aspx这样的页面上你只需要一些代码;
bool userLoggedIn = false;
if (Session["User"] != null) //check the session variable is actually valid
{
if (!String.IsNullOrEmpty(Session["User"]))
{
userLoggedIn = true;
}
}
if (!userLoggedIn)
{
Response.Redirect("login.aspx");
}
虽然在App_Code
文件夹中创建一个类来处理这个问题会更明智,但最后你需要的是遍布整个网站的重复代码。
您遇到的问题是授予用户权利。我不清楚你的问题,但我得到了你想要二进制登录的印象,即:如果用户通过身份验证,他们可以访问,简单明了。如果你是在分段安全之后;控制每个用户可以做什么或不能做什么然后你需要俯视基于声明的安全性的路线,这里有一个例子可以让你思考:http://www.codeproject.com/Articles/2905/Role-based-Security-with-Forms-Authentication
我希望这有助于并且阅读时间不长:)