ASP.NET WebAPI 安全与身份验证 基础验证与非对称加密

因为安全需要,又没有申请HTTPS证书 只对密码进行了非对称加密 同时服务端验证了是否有证书

本文参考了:

MSDN 13年6月的期刊(启用和自定义 ASP.NET Web API 服务的安全性 ):https://msdn.microsoft.com/zh-cn/magazine/dn201748.aspx

与园子里(C#使用RSA证书文件加密和解密示例):http://www.cnblogs.com/eshizhan/archive/2012/10/07/2713680.html

根据实际使用环境做了一定修改:

服务端 HttpModel 验证:

 1  /// <summary>
 2     /// 身份验证
 3     /// </summary>
 4     public class PHVHttpAuthentication : IHttpModule, IDisposable
 5     {
 6         /// <summary>
 7         /// 初始化
 8         /// </summary>
 9         /// <param name="context"></param>
10         public void Init(HttpApplication context)
11         {
12             context.AuthenticateRequest += AuthenticateRequests;
13             context.EndRequest += TriggerCredentials;
14         }
15 
16         private static void TriggerCredentials(object sender, EventArgs e)
17         {
18             HttpResponse resp = HttpContext.Current.Response;
19             if (resp.StatusCode == 401)
20             {
21                 resp.Headers.Add("WWW-Authenticate", @"Basic realm='PHVIS'");
22             }
23         }
24 
25         private static void AuthenticateRequests(object sender, EventArgs e)
26         {
27             System.Web.HttpClientCertificate cert = HttpContext.Current.Request.ClientCertificate;
28 
29             if (cert != null && cert.IsValid) //验证证书是否存在并且有效
30             {
31                 string authHeader = HttpContext.Current.Request.Headers["Authorization"];
32 
33                 if (authHeader != null)
34                 {
35                     AuthenticationHeaderValue authHeaderVal = AuthenticationHeaderValue.Parse(authHeader);
36                     if (authHeaderVal.Parameter != null)
37                     {
38                         byte[] unencoded = Convert.FromBase64String(authHeaderVal.Parameter);
39                         string userpw = Encoding.GetEncoding("iso-8859-1").GetString(unencoded);
40 
41                         string[] creds = userpw.Split(':');
42                         string path = HttpContext.Current.Server.MapPath("~/App_Data/token.pfx");
43                         X509Certificate2 prvcrt = new X509Certificate2(path, "rootshell", X509KeyStorageFlags.Exportable);
44                         RSACryptoServiceProvider prvkey = (RSACryptoServiceProvider)prvcrt.PrivateKey;
45                         var passwordbits = SecurityHelper.RSADecrypt(Convert.FromBase64String(creds[1]), prvkey.ExportParameters(true), false);
46                         var password = Encoding.GetEncoding("iso-8859-1").GetString(passwordbits);
47                         if (creds[0] == "Peter" && password == "123")
48                         {
49                             GenericIdentity gi = new GenericIdentity(creds[0]);
50                             Thread.CurrentPrincipal = new GenericPrincipal(gi, null);
51                             HttpContext.Current.User = Thread.CurrentPrincipal;
52 
53                             //string[] roles = "manager,admin".Split(',');
54                             //Thread.CurrentPrincipal = new GenericPrincipal(gi, roles);
55                         }
56                     }
57                 }
58             }
59             else
60             {
61 
62             }
63 
64 
65         }
66 
67         /// <summary>
68         /// 销毁
69         /// </summary>
70         public void Dispose()
71         {
72 
73         }
74 
75 
76     }
PHVHttpAuthentication

Web.Config配置:

 <modules>
      <add name="EthanAuthorize"  type="Security.PHVHttpAuthentication, Security"/>
    </modules>
Web.Config

完成这两步就已经可以实现对用户名和密码的验证了
接下来就是在需要调用的API上加上AuthorizeAttribute标记既可:

 1  /// <summary>
 2         /// 获取数据
 3         /// </summary>
 4         /// <param name="appId">微信AppD</param>
 5         /// <returns></returns>
 6         [Authorize(Users = "Peter")]
 7         public string Get(string appId)
 8         {
 9             if (User.Identity.IsAuthenticated)
10             {
11                 return "ok";
12             }
13             else
14             {
15                 return "error";
16             }
17         }
Authorize

附上非对称加密的类:

 1  /// <summary>
 2     /// 加密解密类
 3     /// </summary>
 4     public class SecurityHelper
 5     {
 6        
 7         /// <summary>
 8         /// 非对称加密
 9         /// </summary>
10         /// <param name="DataToEncrypt">待加密的数据</param>
11         /// <param name="RSAKeyInfo">公玥信息</param>
12         /// <param name="DoOAEPPadding"></param>
13         /// <returns></returns>
14         public static byte[] RSAEncrypt(byte[] DataToEncrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
15         {
16             try
17             {
18                 byte[] encryptedData;
19                 //Create a new instance of RSACryptoServiceProvider.
20                 using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
21                 {
22 
23                     //Import the RSA Key information. This only needs
24                     //toinclude the public key information.
25                     RSA.ImportParameters(RSAKeyInfo);
26 
27                     //Encrypt the passed byte array and specify OAEP padding.  
28                     //OAEP padding is only available on Microsoft Windows XP or
29                     //later.  
30                     encryptedData = RSA.Encrypt(DataToEncrypt, DoOAEPPadding);
31                 }
32                 return encryptedData;
33             }
34             //Catch and display a CryptographicException  
35             //to the console.
36             catch (CryptographicException e)
37             {
38                 Console.WriteLine(e.Message);
39 
40                 return null;
41             }
42 
43         }
44 
45         /// <summary>
46         /// 非对称解密
47         /// </summary>
48         /// <param name="DataToDecrypt">待解密信息</param>
49         /// <param name="RSAKeyInfo">私钥信息</param>
50         /// <param name="DoOAEPPadding"></param>
51         /// <returns></returns>
52         public static byte[] RSADecrypt(byte[] DataToDecrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
53         {
54             try
55             {
56                 byte[] decryptedData;
57                 //Create a new instance of RSACryptoServiceProvider.
58                 using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
59                 {
60                     //Import the RSA Key information. This needs
61                     //to include the private key information.
62                     RSA.ImportParameters(RSAKeyInfo);
63 
64                     //Decrypt the passed byte array and specify OAEP padding.  
65                     //OAEP padding is only available on Microsoft Windows XP or
66                     //later.  
67                     decryptedData = RSA.Decrypt(DataToDecrypt, DoOAEPPadding);
68                 }
69                 return decryptedData;
70             }
71             //Catch and display a CryptographicException  
72             //to the console.
73             catch (CryptographicException e)
74             {
75                 Console.WriteLine(e.ToString());
76 
77                 return null;
78             }
79 
80         }
81     }
SecurityHelper

客户端的使用代码:

 1  X509Certificate2 pubcrt = new X509Certificate2(System.Web.HttpContext.Current.Server.MapPath("~/App_Data/token.cer"));
 2                     string DefaultUserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
 3                     HttpWebRequest request = WebRequest.Create(string.Format("http://api.xxxxxx.com/api/token?appid={0}", appid)) as HttpWebRequest;
 4                     request.Method = "GET";
 5                     request.UserAgent = DefaultUserAgent;
 6                     request.ClientCertificates.Add(pubcrt);
 7 
 8                     RSACryptoServiceProvider pubkey = (RSACryptoServiceProvider)pubcrt.PublicKey.Key;
 9                     UTF8Encoding ByteConverter = new UTF8Encoding();
10                     byte[] dataToEncrypt = ByteConverter.GetBytes("123");
11                     string password = Convert.ToBase64String(SecurityHelper.RSAEncrypt(dataToEncrypt, pubkey.ExportParameters(false), false));
12 
13                     request.Credentials= new NetworkCredential("Peter", password);
14 
15                     var result= request.GetResponse() as HttpWebResponse;
16 
17                     var sr = new StreamReader(result.GetResponseStream(), Encoding.UTF8);
18 
19                     //返回结果网页(html)代码
20                     string content = sr.ReadToEnd();
View Code
原文地址:https://www.cnblogs.com/neumik/p/5444914.html