用户权限验证 using System; using System.Security; using System.Security.Principal; using System.Collections.Specialized; using System.Xml.Serialization; using System.IO; using System.Runtime.Serialization.Formatters.Binary; namespace security { [Serializable] public sealed class NorthwindCredentials : IPrincipal //接口继承 { private System.Security.Principal.GenericIdentity _Identity;//用户 private StringCollection _roles = new StringCollection();//权限(角色) private DateTime _Created;//创建时间 private bool _properlyInitted = false;//是否初始化 public NorthwindCredentials() { //Required by XML Serialization } //构造函数 public NorthwindCredentials(string UserName, string[] roles) { _Identity = new GenericIdentity(UserName , "NorthwindCredentials"); if(null!=roles) _roles.AddRange(roles); _Created = DateTime.Now; _properlyInitted = true; } #region IPrincipal Members //接口的方法重载 //XML Serialization will barf on this if we don't: [XmlIgnoreAttribute] public IIdentity Identity { get { CheckProperlyInitted(); CheckExpired(); return _Identity; } } //判断是否有权限 public bool IsInRole(string role) { CheckProperlyInitted(); CheckExpired(); return _roles.Contains(role); } //判断用户是否已经创建 private void CheckProperlyInitted() { if(!_properlyInitted) throw new SecurityException( "Principal not properly initialized. Might be spoofed."); } //判断用户是否过期 private void CheckExpired() { if(_Created.AddHours(48) <= DateTime.Now) throw new SecurityException("Credentials have expired."); } #endregion } } 调用: //取得用户名和权限,并保存 private void btnLogin_Click(object sender, EventArgs e) { NorthwindCredentials creds = null; if ("admin" == tbname.Text && "1234" == tbpass.Text) creds = new NorthwindCredentials( tbname.Text, new string[]{ "Admin", "Manager"}); else { if ("fred" == tbname.Text && // 1234 "1234" == tbpass.Text) //hashed password creds = new NorthwindCredentials( tbname.Text, new string[]{"Sales"});//fred is only member of Sales } //本程序和本用户关联起来 System.Threading.Thread.CurrentPrincipal = creds; //窗体控件属性设置(如果用户有manager权限的情况) btnjiami.Enabled = System.Threading.Thread.CurrentPrincipal .IsInRole("Manager"); btnjiemi.Enabled = System.Threading.Thread.CurrentPrincipal .IsInRole("Manager"); //调用方法 showMessage(); } } //通过标识设置函数的访问权限(方法1) [PrincipalPermission(SecurityAction.Demand,Role = "Manager")] private void setStates() { MessageBox.Show("Manager"); } private void showMessage() { //通过程序设置方法的执行(方法2) PrincipalPermission perm = new PrincipalPermission(null,"Sales",true); try { //此处一定要try catch,否则报错“对主体权限的请求失败” perm.Demand(); } catch (System.Security.SecurityException e) { // MessageBox.Show(e.ToString()); return; } MessageBox.Show("Sales"); } 加密 using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace security { //Encapsulates the functionality of encrypting with //the DES encryption algorithm and hashing with MD5 public class Cryptography { //Required for DES stream-based Encryption //实现对称加密 private byte[] _IV;//初始化对象 private byte[] _key;//密码 public Cryptography(string Key) { CreateDESKeyAndVector(Key ,ref _IV ,ref _key); } private void CreateDESKeyAndVector(string Key , ref byte[] KeyOut , ref byte[] InitializationVectorOut) { const int KEY_SIZE_IN_BYTES = 8; //64 bits // Byte array to hold key byte[] arrByte = Encoding.Unicode.GetBytes(Key); //Get the 16-byte hash value of the password SHA1CryptoServiceProvider objSHACryptoServiceProv = new SHA1CryptoServiceProvider(); byte[] arrHash = objSHACryptoServiceProv.ComputeHash( arrByte); KeyOut = (byte[])Array.CreateInstance(typeof(byte),(KEY_SIZE_IN_BYTES)); InitializationVectorOut = (byte[])Array.CreateInstance(typeof(byte), (KEY_SIZE_IN_BYTES)); for(int intCtr = 0;intCtr < KEY_SIZE_IN_BYTES; intCtr++) { //stick the low-order 8 bytes of the hash into the key KeyOut[intCtr] = arrHash[intCtr]; //stick the high-order 8 bytes of the hash into the initialization vector InitializationVectorOut[intCtr] = arrHash[intCtr + KEY_SIZE_IN_BYTES]; } } public string EncryptEncodeString(string EncryptAndEncodeThis) { //convert our input string to a byte array byte[] inputByteArray = Encoding.Unicode.GetBytes( EncryptAndEncodeThis); //now return the byte array as a "safe for XMLDOM" Base64 String //用Base64可以安全的用xml传递二进制数据 return Convert.ToBase64String( Encrypt(inputByteArray)); } public byte[] Encrypt(byte[] EncryptThis) { //now encrypt the bytearray MemoryStream ms = new MemoryStream(); DESCryptoServiceProvider DESProv = new DESCryptoServiceProvider(); CryptoStream cs = new CryptoStream(ms , DESProv.CreateEncryptor(_key, _IV) , CryptoStreamMode.Write); cs.Write(EncryptThis , 0 , EncryptThis.Length); cs.FlushFinalBlock(); return ms.ToArray(); } public string DecodeDecryptString(string EncryptedAndEncodedData) { byte[]inputByteArray = (byte[])Array.CreateInstance(typeof(byte), EncryptedAndEncodedData.Length); // we have a base 64 encoded string so first must decode //to regular unencoded (encrypted) string inputByteArray = Convert.FromBase64String(EncryptedAndEncodedData); //now decrypt the regular string return Encoding.Unicode.GetString(Decrypt(inputByteArray)); } public byte[] Decrypt(byte[] EncryptedData) { MemoryStream ms = new MemoryStream(); DESCryptoServiceProvider DESProv = new DESCryptoServiceProvider(); CryptoStream cs = new CryptoStream(ms , DESProv.CreateDecryptor(_key, _IV) , CryptoStreamMode.Write); cs.Write(EncryptedData, 0, EncryptedData.Length); cs.FlushFinalBlock(); return ms.ToArray(); } public CryptoStream WrapStreamForEncryption(Stream stream) { DESCryptoServiceProvider DESProv = new DESCryptoServiceProvider(); CryptoStream cs = new CryptoStream(stream , DESProv.CreateEncryptor(_key, _IV) , CryptoStreamMode.Write); return cs; } public CryptoStream WrapStreamForDecryption(Stream stream) { DESCryptoServiceProvider DESProv = new DESCryptoServiceProvider(); CryptoStream cs = new CryptoStream(stream , DESProv.CreateDecryptor(_key, _IV) , CryptoStreamMode.Read); return cs; } private static MD5CryptoServiceProvider _md5 = new MD5CryptoServiceProvider(); public static string ComputeHash(string Value) { return ByteArrayToString(_md5.ComputeHash( new UnicodeEncoding().GetBytes(Value))); } static string ByteArrayToString(byte[] arrInput) { int i; StringBuilder sOutput = new StringBuilder(arrInput.Length); for (i=0;i < arrInput.Length; i++) { sOutput.Append(arrInput[i].ToString("X2")); } return sOutput.ToString(); } } } 调用: //加密 private void button2_Click(object sender, EventArgs e) { tbmiwen.Text = new Cryptography(tbkey.Text).EncryptEncodeString( tbmingwen.Text); } //解密 private void btnjiemi_Click(object sender, EventArgs e) { tbmingwen.Text = new Cryptography(tbkey.Text).DecodeDecryptString( tbmiwen.Text); } //生成哈希值 private void btnhash_Click(object sender, EventArgs e) { tbmiwen.Text = Cryptography. ComputeHash(tbmingwen.Text); } Assembly.info设置 // Minimum set: //Need to get to the web service [assembly: System.Net.WebPermission(SecurityAction.RequestMinimum)] //Need to store data in Isolated Storage [assembly:IsolatedStorageFilePermissionAttribute( SecurityAction.RequestMinimum, UserQuota=5242880)] //Need to set the security principal [assembly:SecurityPermissionAttribute( SecurityAction.RequestMinimum, ControlPrincipal=true)] //need to modify the thread exception [assembly:SecurityPermissionAttribute( SecurityAction.RequestMinimum, ControlThread=true)] //need to be able to run... [assembly:SecurityPermissionAttribute( SecurityAction.RequestMinimum, Execution=true)] //need to be able to serialize and deserialize [assembly:SecurityPermissionAttribute( SecurityAction.RequestMinimum, SerializationFormatter = true)] // Refused set: [assembly: System.Data.SqlClient.SqlClientPermission(SecurityAction.RequestRefuse)] [assembly: System.Data.OleDb.OleDbPermission(SecurityAction.RequestRefuse)] 可以在项目目录中通过prenview查看程序的权限。 允许指定的DLL调用本工程的方法 StrongNameIdentityPermission(SecurityAction.LinkDemand, PublicKey=”00240000…d6”,Version=”1.0.0.0”) SQL注入 就是说,如果输入’or 1=1 -- 那么程序永远能通过。 SqlCommand cmd = new SqlCommand("select UserName from Security_tbUser " + " where UserName='" + UserName + "' and Password='" + hashedPass + "'", conn); 这种写法,就会产生漏洞。 SqlCommand cmd = new SqlCommand("select UserName from Security_tbUser" + " where UserName=@UserName and Password=@Password", conn); cmd.Parameters.Add(new SqlParameter("@UserName", UserName)); cmd.Parameters.Add(new SqlParameter("@Password", hashedPass)); bool RetVal = null != cmd.ExecuteScalar(); return RetVal; 这种方法就避免了这个漏洞,所有的检测都有系统自己处理了,如果出错,查询结果返回false。