我正在尝试登录,但不断出现此错误:
System.Data.SqlClient.SqlException:“'USERNAME'附近的语法不正确。”
这是我的代码
SqlConnection con = new SqlConnection(@"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\Omar\Documents\Data.mdf;Integrated Security=True;Connect Timeout=30");
SqlDataAdapter sda = new SqlDataAdapter("Select Count(*) From [LOGIN] were USERNAME ='" + textBox1.Text +"' and PASSWORD='"+ textBox2.Text +"'",con);
DataTable dt = new DataTable();
sda.Fill(dt);
答案 0 :(得分:22)
您之所以被否决,不仅是因为这是一个重复的问题,还因为您的尝试将两个安全性问题包装在了一段代码中。
因此,让我们逐步进行此操作。
1)您的实际问题是您在哪里弄错了。您更正后的代码看起来像
SqlConnection con = new SqlConnection(@"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\Omar\Documents\Data.mdf;Integrated Security=True;Connect Timeout=30");
SqlDataAdapter sda = new SqlDataAdapter("Select Count(*) From [LOGIN] where USERNAME ='" + textBox1.Text +"' and PASSWORD='"+ textBox2.Text +"'",con);
DataTable dt = new DataTable();
sda.Fill(dt);
但是您不需要数据适配器或表,可以直接从SQL返回计数。所以你可以做类似的事情
string sql = "select count(*) from users where username = '" + username + "' and password = '" + password + "'";
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
using (SqlCommand command = new SqlCommand(query, conn))
{
int result = (int)command.ExecuteScalar();
if (result > 0)
{
/// login sucessful
}
}
}
这可以工作,但是您有一个称为SQL注入的安全漏洞。
。如果我们查看正确的登录名,则您的SQL字符串为
select count(*) from login where username = 'alice' and password = 'bob'
这很好用,但是如果我输入登录页面的SQL注入经典示例作为密码' OR 1=1 --
,那么您的SQL字符串就变成这个;
select count(*) from login where username = 'alice' and password = '' OR 1=1 --'
这行SQL将始终返回1,因为它通过SQL注入对SQL进行了劫持,并在语句OR 1=1
的末尾添加了OR子句,该子句总是正确的。然后,它使用SQL注释语法注释掉其后的所有内容。因此,现在我可以以任何人的身份登录,甚至包括不存在的用户名。
2)如果不想使用为您执行此操作的ORM(实际上,使用ORM,所有保护都是自动的),则构建SQL字符串的正确方法是使用parameterized query ,它采用输入格式并设置其格式,以使任何特殊字符都不会被视为SQL命令,例如
string sql = "select count(*) from login where username = @username and password = @password";
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
using (SqlCommand command = new SqlCommand(query, conn))
{
command.Parameters.Add(new SqlParameter("@username", username));
command.Parameters.Add(new SqlParameter("@password", password));
int result = (int)command.ExecuteScalar();
if (result > 0)
{
/// login sucessful
}
}
}
在SQL查询中,参数为@parameterName
,然后与command.Parameters.Add()
添加。现在您避免了SQL注入
3)但是,这仍然是一个安全问题。 您以纯文本格式存储密码。如果我在拥有数据库副本后可以通过SQL注入访问SQL数据库(或者通过使服务器向世界开放),则可以使用您的用户名和密码,而您的公司最终将以{{3 }}。您不应该这样做。密码应该通过haveibeenpwned来保护,而不是通过加密来保护。这会将密码转换为通过单向函数从其派生的值,它将密码取回,并将其输入到一些数学运算中,结果从另一面表示密码,但是您无法返回另一种方式,则无法从加盐的哈希中找出密码。然后,当您比较登录名时,您将再次计算哈希值,并在ORM驱动的查询或参数化查询中将其用于比较中。
现在,考虑到所有这些,我强烈建议您避免自己做任何事情。 C#和ASP.NET在ASP.NET Identity中具有用于用户名和密码的库。我宁愿看到您使用它,不仅是因为我恰好是该应用程序以及整个.NET Security的PM所有者,而且还因为它可以满足您的所有需求,而无需您做任何工作。
如果这是用于真实世界的应用程序,请花一些时间来完成hashing and salting,其中包含许多安全问题的示例以及如何解决这些问题的详细信息。
答案 1 :(得分:14)
请...
IDisposable
;这里涉及的多个对象都是一次性的,需要using
DataTable
,否则请不要使用using (var con = SqlConnection(@"...not shown..."))
{
var hash = HashPasswordUsingUsernameAsSalt(
textBox1.Text, textBox2.Text); // impl not shown
int count = con.QuerySingle<int>(@"
select COUNT(1) from [LOGIN]
where [USERNAME]=@cn and [PW_HASH]=@hash",
new { cn = textBox1.Text, hash });
// TODO: do something with count
}
-没有理由在这里使用并且仅当您具有上述“按下”功能时:修正错字
以下是使用“精简版”的版本,其中涵盖了大部分内容:
'KeyError: u'IteratorGetNext:1'
答案 2 :(得分:2)
在第二行上,您似乎对WHERE子句有错字。
const getUserChoice = (userInput) => {
userInput = userInput.toLowerCase();
if (userInput === 'rock' || userInput === 'paper' || userInput === 'scissors') {
return userInput;
} else {
console.log('Error!');
}
}
const getComputerChoice = () => {
switch (Math.floor(Math.random() * 3)) {
case 0:
return 'rock';
case 1:
return 'paper';
case 2:
return 'scissors';
}
}
const determineWinner = (userChoice, computerChoice) => {
if (userChoice === computerChoice) {
return 'the game was a tie';
}
if (userChoice === 'rock') {
if (computerChoice === 'paper') {
return 'computer won!';
} else {
return 'you won!';
}
}
if (userChoice === 'paper') {
if (computerChoice === 'scissors') {
return 'computer won!';
} else {
return 'you won!';
}
}
if (userChoice === 'scissors') {
if (computerChoice === 'rock') {
return 'computer won!';
} else {
return 'you won!';
}
}
}
const playGame = () => {
const userChoice = getUserChoice('rock');
const computerChoice = getComputerChoice();
console.log(`You threw: ${userChoice}`);
console.log(`The computer threw: ${computerChoice}`);
console.log(determineWinner(userChoice, computerChoice));
};
playGame();
但是,由于您的SQL容易受到黑客攻击,因此您需要了解有关SQL注入攻击的信息。