转:http://blog.csdn.net/yongping8204/article/details/8619577

WebService安全性的几种实现方法【身份识别】

2013-02-27 21:51 7778人阅读 评论(0) 收藏 举报
 分类:
WEB技术(C#)(22) 

相信很多开发者都用过WebService来实现程序的面向服务,本文主要介绍WebService的身份识别实现方式,当然本文会提供一个不是很完善的例子,权当抱砖引玉了.

首先我们来介绍webservice下的两种验证方式,

一.通过集成windows身份验证

通过集成windows方式解决webservice的安全问题是一个很简洁,并且行之有效的解决方案,该方案的优点是比较安全,性能较好,当然因为与windows紧密的结合到了一起,缺点自然也很明显了,第一,不便于移植,第二,要进行相关的配置部署工作(当然我们也可以用代码来操作IIS,只不过比较麻烦,最近一直做自动化部署,所以一讲到配置马上就会联想到怎么去自动部署)

具体怎么做呢?

服务器端:配置IIS虚拟目录为集成windows身份验证

客户端:

Service1 wr = new Service1(); //web service实例

wr.Credentials = new NetworkCredential("administrator","123"); //用户名密码

lblTest.Text = wr.Add(2,2).ToString(); //调用Add的 web service方法

二.使用 SoapHeader(SOAP 标头)自定义身份验证

SoapHeader 多数情况下用来传递用户身份验证信息,当然它的作用远不止如此,有待于在实际应用中发掘,体可以实现哪些东西大家有想法可以留言一起交流.

SoapHeader 使用步骤: 
(1) 创建继承自 System.Web.WebServices.SoapHeader 的自定义 SoapHeader 类型。 
(2) 在 WebService 中创建拥有 public 访问权限的自定义 SoapHeader 字段。 
(3) 在需要使用 SoapHeader 的 WebMethod 上添加 SoapHeaderAttribute 访问特性。SoapHeaderAttribute 构造必须指定 memberName 参数,就是我们在第二步中申明的字段名称。 
(4) 生成器会自动为客户端生成同名的自定义 SoapHeader 类型,只不过比起我们在 WebService 端创建的要复杂一些。同时还会为代理类型添加一个 soapheaderValue 属性。

下面展示一段SoapHeader的代码,多余的方法将会在后面用到

客户端

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. Service1 ws = new Service1();
  6. ServiceCredential mycredential = new ServiceCredential();
  7.  
  8. mycredential.User = "gazi";
  9. mycredential.Password="gazi";
  10. ws.ServiceCredentialValue = mycredential;
  11. string mystr=ws.SayHello();
  12. }
  13. }

服务器端

  1. public class Service1 : System.Web.Services.WebService
  2. {
  3. public ServiceCredential myCredential;
  4.  
  5. [WebMethod]
  6. [SoapHeader("myCredential", Direction = SoapHeaderDirection.In)]
  7. public string SayHello()
  8. {
  9. return "hello";
  10. }
  11. }
  12.  
  13. public class ServiceCredential : SoapHeader
  14. {
  15. public string User;
  16. public string Password;
  17. public static bool ValideUser(string User,string Password)
  18. {
  19. return true;
  20. }
  21. public static void CheckUser(Object sender, WebServiceAuthenticationEvent e)
  22. {
  23. if (ValideUser(e.User, e.Password))
  24. {
  25. return;
  26. }
  27. else
  28. {
  29. WebServiceAuthenticationModule module = sender as WebServiceAuthenticationModule;
  30. module.Result.AddRule("验证错误", "不能确认您的身份,请检查用户名和密码");
  31. }
  32. }
  33. }

当我们拥有很多个类的时候,要添加一个或者删除一个验证方式(假设需要进行多种认证)是非常麻烦的,我们不可能跑到每个方法里面去加一个方法调用,这是灾难性的工作,当然我们也可以用AOP来实现,Aop的话需要额外增加很多代码或者直接引入第三方来做,但是我们可不可以有更简便的方法呢?

OK,答案就是使用HttpModule,我们集成IHttpModule写一个处理模块,那么它的原理是什么呢?具体进行了哪些操作呢?我们的思路如下:

  1. HTTP Module 分析 HTTP 消息以检查它们是不是 SOAP 消息。
  2. 如果 HTTP Module 检测到 SOAP 消息,它会读取 SOAP 标头。
  3. 如果 SOAP 消息的 SOAP 标头中有身份验证凭据,HTTP Module 将引发一个自定义 global.asax 事件。
 

下面来看看我们的Module代码

  1. 1 public class WebServiceAuthenticationModule : IHttpModule
  2. 2 {
  3. 3 private static WebServiceAuthenticationEventHandler
  4. 4 _eventHandler = null;
  5. 5 /// <summary>
  6. 6 /// 验证事件.绑定到此事件可进行对用户身份的识别
  7. 7 /// </summary>
  8. 8 public static event WebServiceAuthenticationEventHandler Authenticate
  9. 9 {
  10. 10 add { _eventHandler = value; }
  11. 11 remove { _eventHandler -= value; }
  12. 12 }
  13. 13 public Result Result = new Result();
  14. 14
  15. 15 public void Dispose()
  16. 16 {
  17. 17 }
  18. 18 public void Init(HttpApplication app)
  19. 19 {
  20. 20 app.AuthenticateRequest = new
  21. 21 EventHandler(this.OnEnter);
  22. 22 Result.EndValid = new
  23. 23 EventHandler(this.OnCheckError);
  24. 24 }
  25. 25
  26. 26 /// <summary>
  27. 27 /// 验证用户身份
  28. 28 /// </summary>
  29. 29 /// <param name="e"></param>
  30. 30 private void OnAuthenticate(WebServiceAuthenticationEvent e)
  31. 31 {
  32. 32 if (_eventHandler == null)
  33. 33 return;
  34. 34
  35. 35 _eventHandler(this, e);
  36. 36 if (e.User != null)
  37. 37 e.Context.User = e.Principal;
  38. 38 }
  39. 39
  40. 40 public string ModuleName
  41. 41 {
  42. 42 get { return "WebServiceAuthentication"; }
  43. 43 }
  44. 44
  45. 45 void OnEnter(Object source, EventArgs eventArgs)
  46. 46 {
  47. 47 HttpApplication app = (HttpApplication)source;
  48. 48 HttpContext context = app.Context;
  49. 49 Stream HttpStream = context.Request.InputStream;
  50. 50
  51. 51 // Save the current position of stream.
  52. 52 long posStream = HttpStream.Position;
  53. 53
  54. 54 // If the request contains an HTTP_SOAPACTION
  55. 55 // header, look at this message.HTTP_SOAPACTION
  56. 56 if (context.Request.ServerVariables["HTTP_SOAPACTION"] == null)
  57. 57 return;
  58. 58
  59. 59 // Load the body of the HTTP message
  60. 60 // into an XML document.
  61. 61 XmlDocument dom = new XmlDocument();
  62. 62 string soapUser;
  63. 63 string soapPassword;
  64. 64
  65. 65 try
  66. 66 {
  67. 67 dom.Load(HttpStream);
  68. 68
  69. 69 // Reset the stream position.
  70. 70 HttpStream.Position = posStream;
  71. 71
  72. 72 // Bind to the Authentication header.
  73. 73 soapUser =
  74. 74 dom.GetElementsByTagName("User").Item(0).InnerText;
  75. 75 soapPassword =
  76. 76 dom.GetElementsByTagName("Password").Item(0).InnerText;
  77. 77 }
  78. 78 catch (Exception e)
  79. 79 {
  80. 80 // Reset the position of stream.
  81. 81 HttpStream.Position = posStream;
  82. 82
  83. 83 // Throw a SOAP exception.
  84. 84 XmlQualifiedName name = new
  85. 85 XmlQualifiedName("Load");
  86. 86 SoapException soapException = new SoapException(
  87. 87 "SOAP请求没有包含必须的身份识别信息", name, e);
  88. 88 throw soapException;
  89. 89 }
  90. 90 // 触发全局事件
  91. 91 OnAuthenticate(new WebServiceAuthenticationEvent
  92. 92 (context, soapUser, soapPassword));
  93. 93 Result.OnEndValid();
  94. 94 return;
  95. 95 }
  96. 96 void OnCheckError(Object sender, EventArgs e)
  97. 97 {
  98. 98 if (Result.BrokenRules.Count == 0)
  99. 99 {
  100. 100 return;
  101. 101 }
  102. 102 else
  103. 103 {
  104. 104 HttpApplication app = HttpContext.Current.ApplicationInstance;
  105. 105 app.CompleteRequest();
  106. 106 app.Context.Response.Write(Result.Error);
  107. 107 }
  108. 108 }
  109. 109 }

Authenticate事件是一个静态的变量,这样我们可以在程序的外部来订阅和取消订阅事件(非静态的public 事件在外部也是不能进行订阅和取消订阅事件的,这也是事件和委托的一个区别之一)

下面是我们的事件参数以及委托

  1. 1 public delegate void WebServiceAuthenticationEventHandler(Object sender, WebServiceAuthenticationEvent e);
  2. 2
  3. 3 /// <summary>
  4. 4 /// 封装的事件参数
  5. 5 /// </summary>
  6. 6 public class WebServiceAuthenticationEvent : EventArgs
  7. 7 {
  8. 8 private IPrincipal _IPrincipalUser;
  9. 9 private HttpContext _Context;
  10. 10 private string _User;
  11. 11 private string _Password;
  12. 12
  13. 13 public WebServiceAuthenticationEvent(HttpContext context)
  14. 14 {
  15. 15 _Context = context;
  16. 16 }
  17. 17
  18. 18 public WebServiceAuthenticationEvent(HttpContext context,
  19. 19 string user, string password)
  20. 20 {
  21. 21 _Context = context;
  22. 22 _User = user;
  23. 23 _Password = password;
  24. 24 }
  25. 25 public HttpContext Context
  26. 26 {
  27. 27 get { return _Context; }
  28. 28 }
  29. 29 public IPrincipal Principal
  30. 30 {
  31. 31 get { return _IPrincipalUser; }
  32. 32 set { _IPrincipalUser = value; }
  33. 33 }
  34. 34 public void Authenticate()
  35. 35 {
  36. 36 GenericIdentity i = new GenericIdentity(User);
  37. 37 this.Principal = new GenericPrincipal(i, new String[0]);
  38. 38 }
  39. 39 public void Authenticate(string[] roles)
  40. 40 {
  41. 41 GenericIdentity i = new GenericIdentity(User);
  42. 42 this.Principal = new GenericPrincipal(i, roles);
  43. 43 }
  44. 44 public string User
  45. 45 {
  46. 46 get { return _User; }
  47. 47 set { _User = value; }
  48. 48 }
  49. 49 public string Password
  50. 50 {
  51. 51 get { return _Password; }
  52. 52 set { _Password = value; }
  53. 53 }
  54. 54 public bool HasCredentials
  55. 55 {
  56. 56 get
  57. 57 {
  58. 58 if ((_User == null) || (_Password == null))
  59. 59 return false;
  60. 60 return true;
  61. 61 }
  62. 62 }
  63. 63 }

我们在Global.asax的Application_Start方法里面把前面介绍的静态方法ServiceCredential.CheckUser订阅到我们Authenticate事件上,前面提到的增加和删除多种认证方式就是通过这种方法实现的.

  1. protected void Application_Start(object sender, EventArgs e)
  2. {
  3. WebServiceAuthenticationModule.Authenticate += ServiceCredential.CheckUser;
  4. }

我们在ServiceCredential.ValideUser方法设置了返回false,这是针对测试的一个配置,实际情况下我们可以和数据库结合起来写一个认证 运行上面讲解SoapHeader的那段代码,你会发现我们的认证已经有效了.关于文章中用到的Result类改天在用一篇文章记录一下,这是一个非常好的记录错误的方案

WebService安全性的几种实现方法【身份识别】的更多相关文章

  1. webservice安全性之 SoapHeader自定义身份验证

    相信很多开发者都用过WebService来实现程序的面向服务,本文主要介绍WebService的身份识别实现方式,当然本文会提供一个不是很完善的例子,权当抱砖引玉了. 首先我们来介绍webservic ...

  2. Liunx 环境下vsftpd的三种实现方法(超详细参数)

    以下文章介绍Liunx 环境下vsftpd的三种实现方法 ftp://vsftpd.beasts.org/users/cevans/vsftpd-2.0.3.tar.gz,目前已经到2.0.3版本.假 ...

  3. iOS 几种加密方法

    iOS常见的几种加密方法 普通加密方法是讲密码进行加密后保存到用户偏好设置中 钥匙串是以明文形式保存,但是不知道存放的具体位置 1.base64加密 base64 编码是现代密码学的基础 基本原理: ...

  4. webservice安全性浅谈

    原文地址:http://www.cnblogs.com/chhuic/archive/2009/11/19/1606109.html 做项目时,经常会用到WebService来通讯,但WebServi ...

  5. 浅淡Webservice、WSDL三种服务访问的方式(附案例)

    Webservice Webservice是使应用程序以与平台和编程语言无关的方式进行相互通信技术. eg:站点提供访问的数据接口:新浪微博.淘宝. 官方解释:它是一种构建应用程序的普遍模型,可以在任 ...

  6. webservice访问的几种方式

    今天在对接的客户用到了webservice,最终采用wsimport生成本地代理方式以SDK的形式对接,但是想的完整的总结一下ws的几种调用方式. 发布服务的IP地址是:192.168.125.116 ...

  7. Axis2开发WebService客户端 的3种方式

    Axis2开发WebService客户端 的3种方式 在dos命令下   wsdl2java        -uri    wsdl的地址(网络上或者本地)   -p  com.whir.ezoffi ...

  8. 精简Docker镜像的五种通用方法

    http://dockone.io/article/8163 精简Docker镜像的好处很多,不仅可以节省存储空间和带宽,还能减少安全隐患.优化镜像大小的手段多种多样,因服务所使用的基础开发语言不同而 ...

  9. Python爬虫突破封禁的6种常见方法

    转 Python爬虫突破封禁的6种常见方法 2016年08月17日 22:36:59 阅读数:37936 在互联网上进行自动数据采集(抓取)这件事和互联网存在的时间差不多一样长.今天大众好像更倾向于用 ...

随机推荐

  1. 小白学习Python遇到的一些2.7与3.X之间的不同问题

    1.输入字母出错问题 原本跟着视频一起学习,currency_str_value=input(‘请输入带单位货币金额’) 但是运行的时候,输入数字就没有问题,只要带上了字母就会报错,后来百度,pyth ...

  2. POJ2777-Count Color (线段树)

    题目传送门:http://poj.org/problem?id=2777 Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Sub ...

  3. Spring Boot 揭秘与实战(二) 数据存储篇 - ElasticSearch

    文章目录 1. 版本须知 2. 环境依赖 3. 数据源 3.1. 方案一 使用 Spring Boot 默认配置 3.2. 方案二 手动创建 4. 业务操作5. 总结 4.1. 实体对象 4.2. D ...

  4. Oracle client安装教程

    一.下载 下载地址:http://download.csdn.net/detail/qq_35624642/9773986 这是Oracle Instant Client的CSDN下载地址. 要注意第 ...

  5. 顶部BANNER

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  6. 树莓派与node.js —— onoff、dht

    1. 发光二极管 tm-onoff var Gpio = require('tm-onoff').Gpio, led = new Gpio(17, 'out'), button = new Gpio( ...

  7. verilog实现中值滤波

    前言 项目需要,想要实现算法中的其中一步即中值滤波,同时,因为图像处理部分中值滤波相对来说还是比较简单的,将中值滤波的硬件实现作为进入FPGA领域的第一次尝试.虽然说网上有较多关于中值滤波的文档,可是 ...

  8. cat命令合并多个txt文件

    cat是concatenate的缩写,意为串联,之前经常看到别人在用cat命令,没有细究 cat命令两个常用的用法是: cat file.txt能够将txt中的内容显示出来 cat file1.txt ...

  9. select标签(分组下拉菜单和列表)

    分组下拉菜单和列表标签: <select name=" " > <optgroup label="组1"> <option val ...

  10. HihoCoder - 1807:好的数字串 (KMP DP)

    Sample Input 6 1212 Sample Output 298 给定一个数字字符串S,如果一个数字字符串(只包含0-9,可以有前导0)中出现且只出现1次S,我们就称这个字符串是好的. 例如 ...