T-SQL创建登录时括号、单引号处理与SQL注入安全问询
先逐个分析你代码里的两个关键部分:
1. 用户名部分:用方括号包裹+校验无右括号,完全安全
在SQL Server里,用[]包裹的标识符(比如登录名、表名)有特殊规则:除了右括号]本身,其他任何字符——不管是单引号'、分号;、注释符--,甚至是换行或者奇怪的符号——都会被当作标识符的一部分,不会被解析成SQL语句的语法元素。
你已经提前校验了用户名不含右括号,所以方括号能完整地把用户名“套”起来,不会出现提前闭合方括号导致的注入漏洞。比如你例子里的john['dow,拼接后变成[john['dow]],SQL Server会把整个john['dow当作登录名,完全没问题,不会把里面的单引号当成SQL语句的一部分。
2. 密码部分:校验无单引号+单引号包裹,同样安全
SQL Server里的字符串常量是用单引号'来闭合的,只有遇到单引号才会结束字符串。你已经确保密码里没有单引号,那不管密码里有什么其他字符——比如mypass; DROP LOGIN test;这种看起来像注入的内容——都会被当作密码的一部分,不会被解析成独立的SQL语句。
举个例子,拼接后的密码部分是PASSWORD = 'mypass; DROP LOGIN test;',SQL Server只会把整个字符串当作密码,不会执行后面的DROP语句,因为它属于字符串常量里的内容,不是可执行的SQL。
额外建议:优先用参数化查询更稳妥
虽然现在的逻辑是安全的,但参数化查询是预防SQL注入的黄金标准——它比手动拼接+校验更可靠,还能避免以后规则变更带来的风险(比如如果以后允许密码包含单引号,手动处理转义很容易出错)。
如果你的ExecSQL支持参数化,建议改成类似这样的伪代码写法:
ExecSQL("CREATE LOGIN @username WITH PASSWORD = @password, CHECK_POLICY = OFF, DEFAULT_DATABASE = Voyager, CHECK_EXPIRATION = OFF", { {"@username", username}, {"@password", password} });
这样不管用户名和密码里有啥特殊字符,都能被安全处理,不用再操心手动校验的问题。
内容的提问来源于stack exchange,提问作者kofifus

