前 言:
项目中,数据库服务器与程序不在一起,且不允许通过互联网直接访问数据库。 解决方法是通过web服务来做中间件来解决数据交互的问题。但如果web服务交互又存在身份验证问题,需要实现访问对应的接口是经过授权的,未授权的是不返回数据。 可能有人说为啥不采取限定IP地址的方式?程序调用没有固定的公网IP。走VPN是一种解决方法,但需要额外的安装软件和设备。
我采用用的方式是每次访问都带上一个key,在web服务器端进行key的校验,如果一致那么返回数据,这样是最简单的方式。 当然最好的做法是访问带上证书,通过证书来校验访问是否授权的。但配置是比较麻烦的。所以我也没有采用这种方式。
但是同样带了一个问题,如果key直接写死在应用中,那么长期不变也存在风险。每次变更key需要重新更新程序也麻烦。所以key最后决定是写入到ini的配置文件中,但这样又带来了另外一个问题,如果ini文件被人获取道了,那不是就可以用key直接访问了?所以这就需要给key来加密,同时在程序中进行解密存储。
实现路径:
一、如何读取ini 配置文件:
1. 安装sunnyUI ,通过Nuget包管理器搜索SunnyUI安装:
sunnyUI是一个c#的winfrom 开源控件库,这里用他工具类库中 IniConfig - ini配置文件类
2. 创建Setting类,实例代码如下
[ConfigFile("Config\\Setting.ini")]
public class Setting : IniConfig<Setting>
{
[ConfigSection("Hello")]
public string SoftName { get; set; }
public string ServerIP { get; set; }
public int ServerPort { get; set; }
public string City { get; set; }
public override void SetDefault()
{
base.SetDefault();
SoftName = "XX软件";
ServerIP = "192.168.1.2";
ServerPort = 9090;
City = "南京";
}
}
3. 类功能解释
[ConfigFile("Config\Setting.ini")]
配置ini文件的位置,当前程序目录下Config目录下的Setting.ini。
*目录不存在时会自动创建目录
[ConfigSection("Hello")]
设置SoftName所在的节点Section的名称,如果不设置则默认为Setup
public override void SetDefault()
当第一次运行时配置文件不存在时,设置配置的默认值,并保存至文件。
- 读取
读取系统配置,并开始应用:
Setting.Current.Load();
TcpClient client = new TcpClient();
client.Connect(Setting.Current.ServerIP, Setting.Current.ServerPort);
Setting.Current.Load();
读取配置信息,将配置文件Setting.ini里的值读取到类的属性中。
这样Setting.Current.ServerIP和Setting.Current.ServerPort就可以直接用了。
如果需要修改配置,修改Setting.ini,重新读取就可以了。
注意:配置读取,属性的应用,都是用的Setting.Current,而不是Setting
- 保存
系统修改配置,并保存到配置文件。
例如系统中修改了获取天气的城市为重庆:
Setting.Current.City = "重庆";
Setting.Current.Save();
修改Setting.Current的属性,并通过Setting.Current.Save()保存即可。
- 其他
通过IniConfig配置文件的应用,屏蔽ini文件常用的通过section,name的字符串值来获取参数的繁琐过程。
1、建议读写的ini文件为IniConfig存储的文件。以免造成文件编码不统一。即先生成这个文件,再进行修改,而不是手动创建配置文件。
2、配置读取,保存类的应用,都是用的Setting.Current,而不是Setting。
二、 字符串的加密和解密
使用SHA1加密、DES加密/解密,网上找的代码
/// <summary>
/// 字符串加密解密类
/// </summary>
public sealed class StringSecurity
{
private StringSecurity() { }
#region SHA1 加密
/// <summary>
/// 使用SHA1加密字符串。
/// </summary>
/// <param name="inputString">输入字符串。</param>
/// <returns>加密后的字符串。(40个字符)</returns>
public static string StringToSHA1Hash(string inputString)
{
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
byte[] encryptedBytes = sha1.ComputeHash(Encoding.ASCII.GetBytes(inputString));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < encryptedBytes.Length; i++)
{
sb.AppendFormat("{0:x2}", encryptedBytes[i]);
}
return sb.ToString();
}
#endregion
#region DES 加密/解密
private static byte[] key = ASCIIEncoding.ASCII.GetBytes("uiertysd");
private static byte[] iv = ASCIIEncoding.ASCII.GetBytes("99008855");
/// <summary>
/// DES加密。
/// </summary>
/// <param name="inputString">输入字符串。</param>
/// <returns>加密后的字符串。</returns>
public static string DESEncrypt(string inputString)
{
MemoryStream ms = null;
CryptoStream cs = null;
StreamWriter sw = null;
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
try
{
ms = new MemoryStream();
cs = new CryptoStream(ms, des.CreateEncryptor(key, iv), CryptoStreamMode.Write);
sw = new StreamWriter(cs);
sw.Write(inputString);
sw.Flush();
cs.FlushFinalBlock();
return Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length);
}
finally
{
if (sw != null) sw.Close();
if (cs != null) cs.Close();
if (ms != null) ms.Close();
}
}
/// <summary>
/// DES解密。
/// </summary>
/// <param name="inputString">输入字符串。</param>
/// <returns>解密后的字符串。</returns>
public static string DESDecrypt(string inputString)
{
MemoryStream ms = null;
CryptoStream cs = null;
StreamReader sr = null;
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
try
{
ms = new MemoryStream(Convert.FromBase64String(inputString));
cs = new CryptoStream(ms, des.CreateDecryptor(key, iv), CryptoStreamMode.Read);
sr = new StreamReader(cs);
return sr.ReadToEnd();
}
finally
{
if (sr != null) sr.Close();
if (cs != null) cs.Close();
if (ms != null) ms.Close();
}
}
#endregion
}
没有花太多功夫去研究,能用就好。
private static byte[] key = ASCIIEncoding.ASCII.GetBytes("uiertysd");
private static byte[] iv = ASCIIEncoding.ASCII.GetBytes("99008855");
key和iv 可以修改为自己的,但是需要是8位。 在ini配置文件中,可以保存密文,读取配置后,使用解密程序解密出来明文的key就可以了。