zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    java Activiti 工作流引擎 SSM 框架模块设计方案
    自定义表单 Flowable 工作流 Springboot vue.js 前后分离 跨域 有代码生成器
    数据库设计的十个最佳实践
    activiti 汉化 stencilset.json 文件内容
    JAVA oa 办公系统模块 设计方案
    java 考试系统 在线学习 视频直播 人脸识别 springboot框架 前后分离 PC和手机端
    集成 nacos注册中心配置使用
    “感恩节 ”怼记
    仓颉编程语言的一点期望
    关于System.out.println()与System.out.print("\n")的区别
  • 原文地址:https://www.cnblogs.com/neumik/p/5444914.html
Copyright © 2011-2022 走看看