最近項目中有個需求,大致說起來就是:公司上線了一個網站,但是需要對這個網站做使用時間限制,也就是常說的授權。
由於時間緊迫,我的實現思路如下:
1、編寫注冊機代碼,用注冊機形成授權文件,授權文件為一個xml字符串,包括開始時間與結束時間節點,然後用加密方法對形成的xml字符串加密
2、將授權文件放到網站發布目錄下,修改原網站中的代碼,解析授權文件中加密的字符串並進一步判斷
實現代碼如下:
注冊機部分代碼:
Base_64 bs = new Base_64();
DateTime dtkssj = dtpKssj.Value;
string ksrq = dtkssj.ToString("yyyy-MM-dd");
DateTime dtjssj = dtpJssj.Value;
string jsrq = dtjssj.ToString("yyyy-MM-dd");
string xmlString = "";
xmlString += "<KSRQ>" + ksrq + "</KSRQ>";
xmlString += "<JSRQ>" + jsrq + "</JSRQ>";
string jmzf = bs.encrypt(xmlString);
string dirPath = Application.StartupPath;
string filePath = dirPath + "\\" + "授權文件,.ini";
if (!File.Exists(filePath))
{
File.Create(filePath);
}
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite);
StreamWriter sw = new StreamWriter(fs);
fs.SetLength(0);
sw.Write(jmzf);
sw.Close();
MessageBox.Show("注冊成功");
注冊機的主體實現思路如上文所說,用特定格式的xml字符串控制,然後用特定方式加密。
加密類的部分代碼:
public string encrypt(string str)
{
int len = str.Length;
if (str == null)
return "";//throw new Exception("NULL pointer.");
if (len == 0)
return str;
string pTmp = "";
pTmp = str;
string dest = "";
for (int i = 0; i < len; i++)
{
char ch = pTmp[i];
int idx1 = ch >> 2 & 0x3f;
int idx2 = ch << 4 & 0x30;
dest += s_keys[idx1];
if (++i == len)
{
dest += s_keys[idx2];
break;
}
//ch = pTmp.charAt(i);
ch = pTmp[i];
idx1 = idx2 | ch >> 4 & 0xf;
idx2 = ch << 2 & 0x3f;
dest += s_keys[idx1];
if (++i == len)
{
dest += s_keys[idx2];
break;
}
ch = pTmp[i];
idx1 = idx2 | ch >> 6 & 0x3;
idx2 = ch & 0x3f;
dest += s_keys[idx1];
dest += s_keys[idx2];
}
return dest;//dest.toString();
}
解密類的部分代碼:
public string decrypt(string str)
{
if (str == null)
return "";//throw new Exception("NULL pointer.");
int len = str.Length;
if (len == 0)
return str;
string dest = "";
//StringBuffer dest = new StringBuffer();
for (int j = 0; j < len; j++)
{
char ch = str[j];
int i;
for (i = 0; i < 64; i++)
if (s_keys[i] == ch)
break;
char tempDest = (char)(i << 2);
if (++j == len)
{
dest += tempDest;
//dest.append(tempDest);
break;
}
ch = str[j];
for (i = 0; i < 64; i++)
if (s_keys[i] == ch)
break;
tempDest |= Convert.ToChar(i >> 4);
dest += tempDest;
//dest.append(tempDest |= i >> 4);
int temp = (i & 0xf) << 4;
if (++j == len)
break;
ch = str[j];
for (i = 0; i < 64; i++)
if (s_keys[i] == ch)
break;
dest += (char)(temp | i >> 2);
//dest.append((char)(temp | i >> 2));
temp = (i & 0x3) << 6;
if (++j == len)
break;
ch = str[j];
for (i = 0; i < 64; i++)
if (s_keys[i] == ch)
break;
dest += (char)(temp | i);
//dest.append((char)(temp | i));
}
return dest;//dest.toString();
}
網站部分解密授權文件部分代碼:
string dirPath = Server.MapPath("");
string filePath = dirPath + "\\" + "授權文件.ini";
if (!System.IO.File.Exists(filePath))
{
//沒有授權文件 顯示未授權
}
else
{
System.IO.StreamReader sr = new System.IO.StreamReader(filePath, Encoding.UTF8);
string content = sr.ReadToEnd().ToString();
sr.Close();
Base_64 bs1 = new Base_64();
string jmzf = bs1.decrypt(content);
System.Xml.XmlDocument xmldoc = new System.Xml.XmlDocument();//實例化一個XmlDocument對像
xmldoc.LoadXml(jmzf);
System.Xml.XmlNode xnKsrq = xmldoc.SelectSingleNode("KSRQ");
string ksrq = xnKsrq.InnerText;
System.Xml.XmlNode xnJsrq = xmldoc.SelectSingleNode("JSRQ");
string jsrq = xnJsrq.InnerText;
DateTime dtKsrq = Convert.ToDateTime(ksrq);
DateTime dtJsrq = Convert.ToDateTime(jsrq);
DateTime dtNow = DateTime.Now.AddDays(1);
int ks = DateTime.Compare(dtKsrq, dtNow);
int js = DateTime.Compare(dtJsrq, dtNow);
if (ks > 0 || js < 0)
{
//顯示授權到期
}
}
在網站代碼中直接獲取到這個授權文件,然後用對稱的方式解密並判斷授權的開始日期與結束日期與服務器日期做比對。
總結:代碼很簡單,甚至是有點簡陋,這裡希望拋磚引玉,有沒有更好的實現思路?這種用文件授權的方式進行的加密是不是容易被破解?。。。
還望各位賜教.....