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 的错误。这个字符串的内容可以自定义,反正服务端根据某种规则检查这个字符串。

  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. }  

然后在每一个服务契约的实现中,都去调用它。 [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 对象。 这样就不用每次调用都去加验证信息了。

  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);  

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

  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. }  


RegisterRoutes 里的工厂类也需要相应的修改下:

  1. var securewebServiceHostFactory = new SecureWebServiceHostFactory();  
  2. RouteTable.Routes.Add(new ServiceRoute("TaskService",  
  3.     securewebServiceHostFactory, typeof(TaskService)));  


这样服务端代码就可以去掉 CheckAuthorization() 而把验证工作都交给 SecureWebServiceHostFactory 了。

 

 

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

posted @ 2016-02-02 16:29  J.Y  阅读(138)  评论(0编辑  收藏  举报