加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

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

发布时间:2020-12-17 00:39:44 所属栏目:安全 来源:网络整理
导读:在REST架构的WCF服务中,它不像一般的WCF服务绑定,有配套的安全模式,实现起来那么简单。REST WCF服务只能在传输层加密,而一般的WCF 服务可以在消息层加密。因此 REST WCF服务启用ASP.NET兼容模式后,它的安全是由ASP.NET来保证的。本篇文章主要介绍在 RES
在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 的错误。这个字符串的内容可以自定义,反正服务端根据某种规则检查这个字符串。

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 对象。
这样就不用每次调用都去加验证信息了。

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 进行拦截校验)

 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 里的工厂类也需要相应的修改下:

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读