当前位置:编程学习 > 网站相关 >>

WCF Security之MembershipProvider+RoleProvider方案

对于web应用(包括web站点及web服务)的安全,我们首先想到的和见到的是,让客户提供凭据(最常见的是用户名和密码),然后服务端对客户提供的凭据进行验证,验证通过后,在具体的方法调用或页面请求时,根据验证通过的客户身份进行授权检查,授权通过,则执行客户的请求;反之则拒绝客户的请求。这就是一般验证及授权的思路。
 
如果这样还不能安全要求,那只好再启用传输层加密,即SSL了。实际上在WCF中,验证方式也被分为两个层次:Transport和Message。在传输层加密数据,在消息层提供凭据验证及授权。本文就准备介绍客户端在消息层传入用户凭据,服务端通过MembershipProvider进行验证,通过RoleProvider进行授权,然后辅以传输层加密的方案。
 
这个方案针对于WCF服务,为了便于客户调用,而又加强传输层安全,所以选择了SSL,另外调用WCF服务又需要提供身份验证及授权,尤其针对凭据信息自定义的要求,客户端凭据选择UserName类型。
这个方案的好处是什么呢?TransportWithMessageCredential确保了传输上的安全,并提供了客户端凭据。而对客户端凭据的验证和授权支持自定义方式,所以不管用什么实现rbac,都可以使用这套方案来实现权限控制。另外,在代码中实现权限控制也比较简单,即使用PrincipalPermissionAttribute。
 
还是让我们开始看看demo吧。
首先然我们定义一个ServiceContract:
[ServiceContract]     

public interface ITestService 

    [OperationContract] 

    string GetData(int value); 

}

 
我们给这个ITestService一个简单的实现:
view sourceprint?public class TestService : ITestService 

    public string GetData(int value) 

    { 

        return string.Format("You entered: {0}", value); 

    } 

}

 
接下来,让我们提供配置信息:
1)Binding配置
view sourceprint?<wsHttpBinding> 

    <binding name="wsHttpBinding1"> 

        <security mode="TransportWithMessageCredential"> 

            <transport clientCredentialType="None" realm="" /> 

            <message clientCredentialType="UserName" /> 

        </security> 

    </binding> 

</wsHttpBinding>

 
2)Service配置
view sourceprint?<service name="TestService.TestService" behaviorConfiguration="securityBehavior"> 

    <endpoint address=""

                  binding="wsHttpBinding"

                  bindingConfiguration ="wsHttpBinding1"

                  contract ="TestBase.ITestService"

                  name ="testService" /> 

    <endpoint address="mex"

                  binding="mexHttpsBinding"

                  contract="IMetadataExchange" /> 

</service>

 
3)MembershipProvider及RoleProvider配置
view sourceprint?<system.web> 

    <roleManager enabled="true" defaultProvider ="MyProvider"> 

        <providers> 

            <add name="MyRoleProvider" type="TestBase.MyRoleProvider,TestBase"/> 

        </providers> 

    </roleManager> 

  

    <membership> 

        <providers> 

            <add name="MyMembershipProvider" type="TestBase.MyMembershipProvider,TestBase"/> 

        </providers> 

    </membership> 

</system.web>

 
4)Behavior配置
view sourceprint?<serviceBehaviors> 

    <behavior name="securityBehavior"> 

        <serviceCredentials> 

            <userNameAuthentication  userNamePasswordValidationMode="MembershipProvider"  membershipProviderName="MyMembershipProvider"/> 

        </serviceCredentials> 

        <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="MyRoleProvider" /> 

    </behavior> 

</serviceBehaviors>

好了,需要的类及配置都已准备好了,然后在IIS中,确保目标Web Site中包含https绑定,并且https绑定指向一个证书。在该Web Site中建立一个Application: TestService。浏览vc">https://localhost/TestService/TestService.svc,可以正常浏览。
接下来,实现客户端调用代码:
view sourceprint?try

    TestServiceReference.TestServiceClient testServiceClient = new TestServiceReference.TestServiceClient ("testService"); 

  

    testServiceClient .ClientCredentials.UserName.UserName = "userName"; 

    testServiceClient .ClientCredentials.UserName.Password = "password"; 

  

    ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) => 

    { 

        return true; 

    }; 

  

    string result = testServiceClient .GetData(3456); 

    Console.WriteLine("result : {0}", result); 

catch (MessageSecurityException ex) 

    //authenticated failed 

    Console.WriteLine(ex.Message); 

catch(SecurityAccessDeniedException ex) 

    //authorized failed 

    Console.WriteLine(ex.Message); 

catch(FaultException ex) 

    Console.WriteLine(ex.Message); 

catch (Exception ex) 

    Console.WriteLine(ex.Message); 

    Console.WriteLine(ex.StackTrace); 

  

Console.ReadLine();

运行,服务可以正常访问。但是权限控制还没有加到服务端代码上,在TestService的GetData方法上加上PrincipalPermissionAttribute:
view sourceprint?public class TestService : ITestService 

    [PrincipalPermission(SecurityAction.Demand, Role = "getData")] 

    public string GetData(int value) 

    { 

补充:综合编程 , 其他综合 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,