WebService安全性的几种实现方法【身份识别】
WebService安全性的几种实现方法【身份识别】
相信很多开发者都用过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的代码,多余的方法将会在后面用到
客户端
class Program
{
static void Main(string[] args)
{
Service1 ws = new Service1();
ServiceCredential mycredential = new ServiceCredential(); mycredential.User = "gazi";
mycredential.Password="gazi";
ws.ServiceCredentialValue = mycredential;
string mystr=ws.SayHello();
}
}
服务器端
public class Service1 : System.Web.Services.WebService
{
public ServiceCredential myCredential; [WebMethod]
[SoapHeader("myCredential", Direction = SoapHeaderDirection.In)]
public string SayHello()
{
return "hello";
}
} public class ServiceCredential : SoapHeader
{
public string User;
public string Password;
public static bool ValideUser(string User,string Password)
{
return true;
}
public static void CheckUser(Object sender, WebServiceAuthenticationEvent e)
{
if (ValideUser(e.User, e.Password))
{
return;
}
else
{
WebServiceAuthenticationModule module = sender as WebServiceAuthenticationModule;
module.Result.AddRule("验证错误", "不能确认您的身份,请检查用户名和密码");
}
}
}
当我们拥有很多个类的时候,要添加一个或者删除一个验证方式(假设需要进行多种认证)是非常麻烦的,我们不可能跑到每个方法里面去加一个方法调用,这是灾难性的工作,当然我们也可以用AOP来实现,Aop的话需要额外增加很多代码或者直接引入第三方来做,但是我们可不可以有更简便的方法呢?
OK,答案就是使用HttpModule,我们集成IHttpModule写一个处理模块,那么它的原理是什么呢?具体进行了哪些操作呢?我们的思路如下:
- HTTP Module 分析 HTTP 消息以检查它们是不是 SOAP 消息。
- 如果 HTTP Module 检测到 SOAP 消息,它会读取 SOAP 标头。
- 如果 SOAP 消息的 SOAP 标头中有身份验证凭据,HTTP Module 将引发一个自定义 global.asax 事件。
下面来看看我们的Module代码
1 public class WebServiceAuthenticationModule : IHttpModule
2 {
3 private static WebServiceAuthenticationEventHandler
4 _eventHandler = null;
5 /// <summary>
6 /// 验证事件.绑定到此事件可进行对用户身份的识别
7 /// </summary>
8 public static event WebServiceAuthenticationEventHandler Authenticate
9 {
10 add { _eventHandler = value; }
11 remove { _eventHandler -= value; }
12 }
13 public Result Result = new Result();
14
15 public void Dispose()
16 {
17 }
18 public void Init(HttpApplication app)
19 {
20 app.AuthenticateRequest = new
21 EventHandler(this.OnEnter);
22 Result.EndValid = new
23 EventHandler(this.OnCheckError);
24 }
25
26 /// <summary>
27 /// 验证用户身份
28 /// </summary>
29 /// <param name="e"></param>
30 private void OnAuthenticate(WebServiceAuthenticationEvent e)
31 {
32 if (_eventHandler == null)
33 return;
34
35 _eventHandler(this, e);
36 if (e.User != null)
37 e.Context.User = e.Principal;
38 }
39
40 public string ModuleName
41 {
42 get { return "WebServiceAuthentication"; }
43 }
44
45 void OnEnter(Object source, EventArgs eventArgs)
46 {
47 HttpApplication app = (HttpApplication)source;
48 HttpContext context = app.Context;
49 Stream HttpStream = context.Request.InputStream;
50
51 // Save the current position of stream.
52 long posStream = HttpStream.Position;
53
54 // If the request contains an HTTP_SOAPACTION
55 // header, look at this message.HTTP_SOAPACTION
56 if (context.Request.ServerVariables["HTTP_SOAPACTION"] == null)
57 return;
58
59 // Load the body of the HTTP message
60 // into an XML document.
61 XmlDocument dom = new XmlDocument();
62 string soapUser;
63 string soapPassword;
64
65 try
66 {
67 dom.Load(HttpStream);
68
69 // Reset the stream position.
70 HttpStream.Position = posStream;
71
72 // Bind to the Authentication header.
73 soapUser =
74 dom.GetElementsByTagName("User").Item(0).InnerText;
75 soapPassword =
76 dom.GetElementsByTagName("Password").Item(0).InnerText;
77 }
78 catch (Exception e)
79 {
80 // Reset the position of stream.
81 HttpStream.Position = posStream;
82
83 // Throw a SOAP exception.
84 XmlQualifiedName name = new
85 XmlQualifiedName("Load");
86 SoapException soapException = new SoapException(
87 "SOAP请求没有包含必须的身份识别信息", name, e);
88 throw soapException;
89 }
90 // 触发全局事件
91 OnAuthenticate(new WebServiceAuthenticationEvent
92 (context, soapUser, soapPassword));
93 Result.OnEndValid();
94 return;
95 }
96 void OnCheckError(Object sender, EventArgs e)
97 {
98 if (Result.BrokenRules.Count == 0)
99 {
100 return;
101 }
102 else
103 {
104 HttpApplication app = HttpContext.Current.ApplicationInstance;
105 app.CompleteRequest();
106 app.Context.Response.Write(Result.Error);
107 }
108 }
109 }
Authenticate事件是一个静态的变量,这样我们可以在程序的外部来订阅和取消订阅事件(非静态的public 事件在外部也是不能进行订阅和取消订阅事件的,这也是事件和委托的一个区别之一)
下面是我们的事件参数以及委托
1 public delegate void WebServiceAuthenticationEventHandler(Object sender, WebServiceAuthenticationEvent e);
2
3 /// <summary>
4 /// 封装的事件参数
5 /// </summary>
6 public class WebServiceAuthenticationEvent : EventArgs
7 {
8 private IPrincipal _IPrincipalUser;
9 private HttpContext _Context;
10 private string _User;
11 private string _Password;
12
13 public WebServiceAuthenticationEvent(HttpContext context)
14 {
15 _Context = context;
16 }
17
18 public WebServiceAuthenticationEvent(HttpContext context,
19 string user, string password)
20 {
21 _Context = context;
22 _User = user;
23 _Password = password;
24 }
25 public HttpContext Context
26 {
27 get { return _Context; }
28 }
29 public IPrincipal Principal
30 {
31 get { return _IPrincipalUser; }
32 set { _IPrincipalUser = value; }
33 }
34 public void Authenticate()
35 {
36 GenericIdentity i = new GenericIdentity(User);
37 this.Principal = new GenericPrincipal(i, new String[0]);
38 }
39 public void Authenticate(string[] roles)
40 {
41 GenericIdentity i = new GenericIdentity(User);
42 this.Principal = new GenericPrincipal(i, roles);
43 }
44 public string User
45 {
46 get { return _User; }
47 set { _User = value; }
48 }
49 public string Password
50 {
51 get { return _Password; }
52 set { _Password = value; }
53 }
54 public bool HasCredentials
55 {
56 get
57 {
58 if ((_User == null) || (_Password == null))
59 return false;
60 return true;
61 }
62 }
63 }
我们在Global.asax的Application_Start方法里面把前面介绍的静态方法ServiceCredential.CheckUser订阅到我们Authenticate事件上,前面提到的增加和删除多种认证方式就是通过这种方法实现的.
protected void Application_Start(object sender, EventArgs e)
{
WebServiceAuthenticationModule.Authenticate += ServiceCredential.CheckUser;
}
我们在ServiceCredential.ValideUser方法设置了返回false,这是针对测试的一个配置,实际情况下我们可以和数据库结合起来写一个认证 运行上面讲解SoapHeader的那段代码,你会发现我们的认证已经有效了.关于文章中用到的Result类改天在用一篇文章记录一下,这是一个非常好的记录错误的方案
WebService安全性的几种实现方法【身份识别】的更多相关文章
- webservice安全性之 SoapHeader自定义身份验证
相信很多开发者都用过WebService来实现程序的面向服务,本文主要介绍WebService的身份识别实现方式,当然本文会提供一个不是很完善的例子,权当抱砖引玉了. 首先我们来介绍webservic ...
- Liunx 环境下vsftpd的三种实现方法(超详细参数)
以下文章介绍Liunx 环境下vsftpd的三种实现方法 ftp://vsftpd.beasts.org/users/cevans/vsftpd-2.0.3.tar.gz,目前已经到2.0.3版本.假 ...
- iOS 几种加密方法
iOS常见的几种加密方法 普通加密方法是讲密码进行加密后保存到用户偏好设置中 钥匙串是以明文形式保存,但是不知道存放的具体位置 1.base64加密 base64 编码是现代密码学的基础 基本原理: ...
- webservice安全性浅谈
原文地址:http://www.cnblogs.com/chhuic/archive/2009/11/19/1606109.html 做项目时,经常会用到WebService来通讯,但WebServi ...
- 浅淡Webservice、WSDL三种服务访问的方式(附案例)
Webservice Webservice是使应用程序以与平台和编程语言无关的方式进行相互通信技术. eg:站点提供访问的数据接口:新浪微博.淘宝. 官方解释:它是一种构建应用程序的普遍模型,可以在任 ...
- webservice访问的几种方式
今天在对接的客户用到了webservice,最终采用wsimport生成本地代理方式以SDK的形式对接,但是想的完整的总结一下ws的几种调用方式. 发布服务的IP地址是:192.168.125.116 ...
- Axis2开发WebService客户端 的3种方式
Axis2开发WebService客户端 的3种方式 在dos命令下 wsdl2java -uri wsdl的地址(网络上或者本地) -p com.whir.ezoffi ...
- 精简Docker镜像的五种通用方法
http://dockone.io/article/8163 精简Docker镜像的好处很多,不仅可以节省存储空间和带宽,还能减少安全隐患.优化镜像大小的手段多种多样,因服务所使用的基础开发语言不同而 ...
- Python爬虫突破封禁的6种常见方法
转 Python爬虫突破封禁的6种常见方法 2016年08月17日 22:36:59 阅读数:37936 在互联网上进行自动数据采集(抓取)这件事和互联网存在的时间差不多一样长.今天大众好像更倾向于用 ...
随机推荐
- phpcms 新建模块安装
1.安装配置---小问题: 估计就我这么傻 T-T ,改成自己的目录名. 2.模块的目录: 模块存放在modules文件夹里,打开这个文件夹,里面的一个文件夹代表一个模块. 3.建立模块以及其基本目 ...
- maven导出项目依赖的jar包
摘要: 在进行项目部署时,需要将maven项目所依赖的jar导出到指定目录,本文讲解如何导出项目依赖的jar包 一.导出到默认目录 targed/dependency 从Maven项目中导出项目依赖的 ...
- Threejs着色器基本使用样例改造
<!DOCTYPE html> <html lang="en"> <head> <title>three.js webgl - bu ...
- C/C++内存泄漏检测 —— memleax
memleax是个开源项目,原理是通过注入hook目标进程的malloc(new也是用的malloc)内存分配函数,在指定时间未释放则认为内存泄漏.优点是不需要重启,attach到目标进程. gith ...
- jquery使用ajax提交form表单
$.ajax({ type: jqform.attr('method'), // 提交方式 get/post url: jqform.attr('action'), // 需要提交的 url data ...
- Linux 下 SVN服务器搭建
使用Linux(CentOS)搭建SVN服务器全攻略 虽然在windows上搭建SVN很简单,但是效能却不高,这当然是和linux相比了.然而在linux上搭建SVN却非常繁琐,所以今天这篇文章就来一 ...
- 在django中进行MySQL入库
在django中进行mysql 入库 需要导入 : from django.db import models 在添加主键时,需要使用: primary_key=True id = models. ...
- UVA10294 Arif in Dhaka (First Love Part 2)
题意 PDF 分析 用n颗宝石串成项链和手镯, 每颗宝石的颜色可以t种颜色中的一种,当A类项链经过旋转得B类项链时,A和B属于一类项链, 而手镯不仅可以旋转还可以翻转,当A类手镯经过翻转得得到B类手镯 ...
- centos7部署phpipam(ip管理系统)
安装必要的软件 yum install httpd mariadb-server php php-cli php-gd php-common php-ldap php-pdo php-pear php ...
- Airtest Project的探索和使用
Airtest使用参考博文: https://testerhome.com/topics/12391 1. 安装Python 3 2. 安装pip: 安装方法参考另外一篇随笔 pip3部署: C:\U ...