如何保护存储在web.config中的密码?

时间:2014-01-03 16:37:54

标签: c# asp.net asp.net-mvc iis web-config

我在web.config文件中添加了以下设置,以启动对外部系统的API调用。所以我按如下方式存储API URL +用户名+密码: -

<appSettings>
    <add key="ApiURL" value="https://...../servlets/AssetServlet" />
    <add key="ApiUserName" value="tmsservice" />
    <add key="ApiPassword" value="test2test2" /> 

然后在我的action方法中,我将在构建Web客户端时引用这些值,如下所示: -

public ActionResult Create(RackJoin rj, FormCollection formValues)
        {
           XmlDocument doc = new XmlDocument();
           using (var client = new WebClient())
                {
                    var query = HttpUtility.ParseQueryString(string.Empty);
                    foreach (string key in formValues)
                    {
                        query[key] = this.Request.Form[key];
                    }

                    query["username"] = System.Web.Configuration.WebConfigurationManager.AppSettings["ApiUserName"];
                    query["password"] = System.Web.Configuration.WebConfigurationManager.AppSettings["ApiPassword"];

                    string apiurl = System.Web.Configuration.WebConfigurationManager.AppSettings["ApiURL"];

但是在这里,我将公开用户名和密码,这些可以被用户捕获,所以我的问题是如何保护API用户名和密码?

6 个答案:

答案 0 :(得分:23)

你可以encrypt the web.config with aspnet_regiis。这是为了阻止有权访问您服务器的人阅读敏感信息。

顺便说一下,我会把你的配置设置放在一个类中,然后可以将它注入到你的控制器中 - 它会使单元测试变得更容易。

答案 1 :(得分:13)

通常,web.config是一个安全文件,IIS不提供它,因此它不会向向Web服务器发出请求的用户公开。 Web服务器只提供特定类型的文件,web.config肯定不是'em。

之一

通常会在其中保存包含密码的数据库连接字符串。现在想象一下web.config不安全的场景。您已经为您的应用程序创建了一个主要的安全威胁。

因此,特别是只要你的项目不是太大,你就不应该担心它。

然而,您可能有更好的方法,但创建一个名为“资源”的项目,并保存所有关键信息,如设置,consts,枚举等。这将是一个光滑和有组织的方法。

如果您通过网络传递用户名/密码(例如在安全的API调用的情况下),您可能希望使用https来确保正在传输的信息是加密的但与此无关web.config文件的安全性。

答案 2 :(得分:3)

web.config文件只是文件系统上的一个文件,因此您应该(大多数)以与其他任何文件相同的方式考虑其安全性。它不会由IIS提供(除非您对IIS进行了一次坦率的疯狂配置更改 - 易于检查,只需尝试通过浏览器请求它)

优良作法是使用文件夹权限保护您的网站目录(c:/ sites / my-site-here或其他),仅使用网站应用程序域用户来读取文件(如果需要,还可以使用部署用户)普通的Windows文件权限

因此,如果您对Web服务器的安全性有信心,则可能没有必要进行加密。但是,如果您说共享主机,或销售网站代码,或源代码是公开的,那么加密它可能是明智的。但是有点麻烦。

答案 3 :(得分:2)

为什么要使用Web.config?

在Web.config中使用数据而不是将其存储在常量,枚举等中的优势之一是,您可以轻松地更改不同环境中的数据。

保护数据

保护Web.config中数据的最佳方法是加密它们。而不是按照Joeuser1089766的建议加密配置文件中的整个部分,您只需加密密码字符串并将其存储在配置中即可。

检索数据

您可以使用下面的帮助函数来解密密钥。

private const readonly string decryptKey = "";
public string GetFromConfig(string key)
{
   var encryptedText = System.Web.Configuration.WebConfigurationManager.AppSettings[key];
   var plainText = Decrypt(encryptedText, decryptKey);
   return plainText;
}

通过这种方式,解密密钥将位于所有环境的公共项目内。但您可以轻松更改web.config中的数据,而无需重新编译应用程序。

PS :您可以更改每个版本的decryptionKey和相应数据,以提高安全性。

答案 4 :(得分:1)

我必须鼓励您将代码与密钥分开。即使您加密了文件,有人也可以从您的存储库中克隆它,并且在加密后,您可能无法再跟踪该文件,或者将来可能会访问密钥等。

加上 Art 指出的(可能还有线程中的其他人),这使得为 Dev / Test / Prod / 等拥有一组单独的密钥非常容易。如果你加密文件,听起来你要么在所有这些环境中具有相同的加密数据和解密密钥。你不一定有一个简单的方法来改变一个而不是其他的。

考虑长期的游戏 - 不仅仅是密码,还应该加载其他配置信息并且每个环境都是唯一的(API 密钥等)

我们也为开发者使用这种方法。我不希望每个开发人员都拥有自己的 API 密钥、密码等,因此他们无法访问不需要的系统。如果开发笔记本电脑丢失,我可以关闭用户的 API 密钥。我可以轮换开发/测试/生产 API 密钥,只需担心在一个地方更改,无需通知所有用户文件已更新,他们需要重新克隆。

答案 5 :(得分:0)

我知道这听起来像是过度工程化,但如果可以,您确实应该使用机密管理服务,例如 AWS Secrets Manager 或 Azure Key Vault。

通过在 web.config 或 app.config 中存储您的密码,即使是加密形式,您也会为自己带来几个问题:

  • 现在您的加密密码将提交给您的源代码管理,使任何具有读取权限的人都可以访问它们。要正确摆脱它们,您需要执行一个 history rewrite(如果您使用的是 git),这是一个主要的痛苦
  • 虽然从技术上讲,您可以将密码放在机器级配置中,并且不在源代码管理中,但您需要在密码更改时更新所有这些文件
  • 现在知道您的加密密码的任何人都可以尝试使用 aspnet_regiis.exe 工具对其进行解密(如果您曾经使用过该工具对其进行加密),或者如果您 rolled your own security 使用您的来源对其进行逆向工程代码,找出它使用的解密算法和密钥
  • 每当您需要更改密码时,您都需要更改该文件并重新部署应用程序。

另一方面,当您使用机密管理服务时,源代码中不会存储任何机密或解密密钥或算法。检索秘密就像这样简单:

对于 Azure Key Vault:

var keyVaultUrl = "https://<your-key-vault-name>.vault.azure.net/";
var credential =  new DefaultAzureCredential();    
var client = new SecretClient(vaultUri: new Uri(keyVaultUrl), credential);    
KeyVaultSecret secret = client.GetSecret("<your-secret-name>");    
Console.WriteLine($"{secret.Name}: {secret.Value}");

对于 AWS Secrets Manager(跳过了一些错误处理代码):

var client = new AmazonSecretsManagerClient(accessKeyId, secretAccessKey, 
                                            RegionEndpoint.APSoutheast2);
var request = new GetSecretValueRequest {
    SecretId = secretName
};
GetSecretValueResponse response = null;
response = client.GetSecretValueAsync(request).Result;

与存储本地机密相比,这种方法有很多优势:

  • 您不必在 Prod/Staging/Dev 环境的配置中存储不同的值——只需读取适当命名的机密(例如“[Dev|Prod|Stag]DBPassword`
  • 只有少数人可以访问非常重要的机密(例如,我不知道,说 Transfer all $$$ from Deus account to all E-Coin wallets everywhere 授权码)
  • 如果有人窃取了您的源代码(心怀不满的员工、意外泄露),则您的密码并未泄露
  • 更改密码很容易——您只需使用 can 管理控制台更新密码并重新启动应用程序

我在我的博客上写了几篇文章,展示了如何使用 AWS 和 Azure 设置和读取机密,如果您需要分步说明和完整的源代码,请随时查看: