WCF4.0 –- RESTful WCF Services (4) (Basic Security) 【转】

http://blog.csdn.net/fangxing80/article/details/6263780

在REST架构的WCF服务中,它不像一般的WCF服务绑定,有配套的安全模式,实现起来那么简单。REST WCF服务只能在传输层加密,而一般的WCF 服务可以在消息层加密。因此 REST WCF服务启用ASP.NET兼容模式后,它的安全是由ASP.NET来保证的。本篇文章主要介绍在 REST WCF 中如何实现最简单的 Username 验证。
在SOAP协议的WCF中,可以通过SOAPHeader(MessageHeader)来实现用户名密码的传输,早在WebService时代我们就这么用过了。在REST WCF中,我们可以利用 HttpHeader 来完成这一目标。 (你可不会想在每个服务契约里加上用户和密码的参数吧...)
首先在服务中加入如下方法用于校验,Header的信息:如果 Header 中 Authorization 的字符串不是"fangxing/123" 那么就将返回 405 MethodNotAllowed 的错误。这个字符串的内容可以自定义,反正服务端根据某种规则检查这个字符串。

[c-sharp] view plain copy print?
  1. private bool CheckAuthorization()  
  2. {  
  3.     var ctx = WebOperationContext.Current;  
  4.     var auth = ctx.IncomingRequest.Headers[HttpRequestHeader.Authorization];  
  5.     if (string.IsNullOrEmpty(auth) || auth != "fangxing/123")  
  6.     {  
  7.         ctx.OutgoingResponse.StatusCode = HttpStatusCode.MethodNotAllowed;  
  8.         return false;  
  9.     }  
  10.     return true;  
  11. }  

private bool CheckAuthorization() { var ctx = WebOperationContext.Current; var auth = ctx.IncomingRequest.Headers[HttpRequestHeader.Authorization]; if (string.IsNullOrEmpty(auth) || auth != "fangxing/123") { ctx.OutgoingResponse.StatusCode = HttpStatusCode.MethodNotAllowed; return false; } return true; } 然后在每一个服务契约的实现中,都去调用它。 [WebGet(UriTemplate = "All")] public List<Task> GetTask() {     if (!CheckAuthorization())         return null;     return GetData(); }

 

[WebGet(UriTemplate = "{taskId}")] public Task GetTaskById(string taskId) {     if (!CheckAuthorization())         return null;     return GetData().FirstOrDefault(t => t.Id==taskId); }
现在的服务,如果直接通过浏览器访问,将得到 405 MethodNotAllowed 的错误:
客户端只要相应的验证信加到 RequestHeader 中去,就可以访问了。客户端可以使用单例模式设计 Client 对象。 这样就不用每次调用都去加验证信息了。

[c-sharp] view plain copy print?
  1. var url = "http://localhost:3433/TaskService/All";  
  2. var client = new HttpClient();  
  3. client.DefaultHeaders.Add("Authorization", "fangxing/123");  
  4. var resp = client.Get(url);  

var url = "http://localhost:3433/TaskService/All"; var client = new HttpClient(); client.DefaultHeaders.Add("Authorization", "fangxing/123"); var resp = client.Get(url); * 这里使用的是 Microsoft.Http.HttpClient (WCF REST Starter Kit) 而非 System.Net.WebClient 
回头看服务端代码,每个服务实现中都需要加上 CheckAuthorization() 是不是很烦? OK,我们知道这个 REST WCF服务是承载在一个Web Application上的, 通过往 RouteTable 中注册 WebServiceHostFactory 来激活服务对象的。 那么只要对这个 WebServiceHostFactory 做些“手脚”,就可以实现服务端验证的统一拦截,代码如下。(一般的 WCF 也可以利用此方法对 MessageHeader 进行拦截校验)

[c-sharp] view plain copy print?
  1. public class SecureWebServiceHostFactory : WebServiceHostFactory  
  2. {  
  3.     protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)  
  4.     {  
  5.         var host = base.CreateServiceHost(serviceType, baseAddresses);  
  6.         host.Authorization.ServiceAuthorizationManager = new MyServiceAuthorizationManager();  
  7.         return host;  
  8.     }  
  9.   
  10.     public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)  
  11.     {  
  12.         var host = base.CreateServiceHost(constructorString, baseAddresses);  
  13.         host.Authorization.ServiceAuthorizationManager = new MyServiceAuthorizationManager();  
  14.         return host;  
  15.     }  
  16. }  
  17.   
  18. public class MyServiceAuthorizationManager : ServiceAuthorizationManager  
  19. {  
  20.     protected override bool CheckAccessCore(OperationContext operationContext)  
  21.     {  
  22.         var ctx = WebOperationContext.Current;  
  23.         var auth = ctx.IncomingRequest.Headers[HttpRequestHeader.Authorization];  
  24.         if (string.IsNullOrEmpty(auth) || auth != "fangxing/123")  
  25.         {  
  26.             ctx.OutgoingResponse.StatusCode = HttpStatusCode.MethodNotAllowed;  
  27.             return false;  
  28.         }  
  29.         return true;  
  30.     }  
  31. }  

public class SecureWebServiceHostFactory : WebServiceHostFactory { protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) { var host = base.CreateServiceHost(serviceType, baseAddresses); host.Authorization.ServiceAuthorizationManager = new MyServiceAuthorizationManager(); return host; } public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses) { var host = base.CreateServiceHost(constructorString, baseAddresses); host.Authorization.ServiceAuthorizationManager = new MyServiceAuthorizationManager(); return host; } } public class MyServiceAuthorizationManager : ServiceAuthorizationManager { protected override bool CheckAccessCore(OperationContext operationContext) { var ctx = WebOperationContext.Current; var auth = ctx.IncomingRequest.Headers[HttpRequestHeader.Authorization]; if (string.IsNullOrEmpty(auth) || auth != "fangxing/123") { ctx.OutgoingResponse.StatusCode = HttpStatusCode.MethodNotAllowed; return false; } return true; } }
RegisterRoutes 里的工厂类也需要相应的修改下:

[c-sharp] view plain copy print?
  1. var securewebServiceHostFactory = new SecureWebServiceHostFactory();  
  2. RouteTable.Routes.Add(new ServiceRoute("TaskService",  
  3.     securewebServiceHostFactory, typeof(TaskService)));  

var securewebServiceHostFactory = new SecureWebServiceHostFactory(); RouteTable.Routes.Add(new ServiceRoute("TaskService", securewebServiceHostFactory, typeof(TaskService)));
这样服务端代码就可以去掉 CheckAuthorization() 而把验证工作都交给 SecureWebServiceHostFactory 了。

 

 

这种验证方式,其实也是现在 Windows Auzer Access Control 的原型。 只不过这个 Authoriztion 的服务是专门的Services罢了。 1. 客户端先从发布令牌的服务获取令牌; 2. 客户端拿着令牌提交到现在的服务; 3.服务端将客户端令牌拿到发布令牌的服务上校验。
源码下载:http://download.csdn.net/download/fangxinggood/3686322

转载于:https://www.cnblogs.com/yf2011/articles/5177893.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值