• 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
  • 相关阅读:
    activity启动模式
    Android自定义view:折线图(附带动画效果)
    支付宝开发接口 Multiple dex files define Lcom/ta/utdid2/device/UTDevice
    android 开发中应用到的单例模式
    新浪微博分享错误代码 10014
    android Model与View解耦的一个简单方式
    android studio 新建项目导入到Coding远程仓库git
    一起学习MVC(2)数据库设计
    ASP.NET MVC :MVC页面验证与授权
    ASP.net:水晶报表的5种表格设计模式
  • 原文地址:https://www.cnblogs.com/neumik/p/5444914.html
Copyright © 2020-2023  润新知