WCF 服务:使用 AD 对 WebGet 和 WebInvoke 的限制 - 匿名访问网站的安全角色

WCF service: restrictions for WebGet and WebInvoke with AD - security roles for a website with anonymous access

我用 WebGet 和 WebInvoke 方法编写了一个 WCF 服务。它到目前为止有效(经过大量试验和错误:-)

但现在我无法让使用 AD 安全角色的限制发挥作用。 我需要限制对 WebInvoke 方法 SetBoxPosition 的访问,该方法用于将数据写入我的服务。

唯一有效的限制是下面 web.config <location> 中对 "ZES_R" 和 "ZES_RW" 的限制。但顾名思义:ZES_R 应该读取和 ZES_RW 读取和写入 (post) ...

我尝试了来自广大互联网的各种代码... IE。来自 https://ramanisandeep.wordpress.com/2014/11/24/wcf-security-how-do-i-restrict-user-access-to-methods-in-wcf/

[PrincipalPermission(SecurityAction.Demand, Role = "ZES_rw")]
public String SetBoxPosition(PostBoxData postBoxData)
{ .....

或制作自定义 ServiceAuthorizationManager。

public class MyServiceAuthorizationManager : ServiceAuthorizationManager
{
        protected override bool CheckAccessCore(OperationContext operationContext)
        {
            try
            {
                ServiceSecurityContext securityContext = operationContext.ServiceSecurityContext;
                WindowsIdentity callingIdentity = securityContext.WindowsIdentity;

                WindowsPrincipal principal = new WindowsPrincipal(callingIdentity);
                return principal.IsInRole("rdm-WEB-Reas_rw");
            }
            catch (Exception)
            {
                return false;
            }
        }
    }

调试函数 CheckAccessCore 时创建的 WindowsPrincipal principal 似乎是空的/匿名的,至少 Name = "" 和 Type = Anonymous,虽然我必须输入我的 Windows 运行 服务的凭据。

出于各种(部分是历史原因)原因,页面本身的配置允许匿名访问。

web.config 中,我通过不同的“位置”部分限制访问,如下所示。

我曾尝试关闭匿名访问,但随后出现错误:

System.ServiceModel.ServiceActivationException

因为我不想失去匿名访问权限,所以我没有进一步挖掘......

有人知道如何让它工作吗?

并且:如果我的代码中的其他内容是伪造的(除了我的拼写),请告诉我:-)

接口:

namespace ZES
{
    [ServiceContract(Namespace = "ZESDataService")]
    public interface IZESData
    {
        [OperationContract]
        [WebGet]
        string Hallo();

        [OperationContract]
        [WebInvoke(Method = "POST",RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle= WebMessageBodyStyle.WrappedRequest)]
        String SetBoxPosition(PostBoxData postBoxData);
    }
    [DataContract]
    public class PostBoxData
    {
        [DataMember] public int BoxID { get; set; }
        [DataMember] public char Bundesland { get; set; }
        [DataMember] public Decimal Latitude { get; set; }
        [DataMember] public Decimal Longtitude { get; set; }
    }
}

ZESData.svc:

<%@ ServiceHost Language="C#" Debug="true" Service="ZES.ZESData" CodeBehind="ZESData.svc.cs" %>

ZESData.svc.cs

namespace ZES
{
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public partial class ZESData : IZESData
    {
        public string Hallo()
        {
            //Simple func 4 testing
            return "Hallo Welt";
        }
        public String SetBoxPosition(PostBoxData postBoxData)
        {
            //function used 4 writing Data to Database
            return SetBoxPos(postBoxData.BoxID, postBoxData.Bundesland, postBoxData.Latitude, postBoxData.Longtitude);
        }
    }
}

web.config

<configuration>
  <appSettings/>
  <system.web>
    <compilation debug="true" targetFramework="4.0">
    </compilation>
    <authentication mode="Windows"/>
    <customErrors mode="Off"/>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
  </system.webServer>
  <system.serviceModel>
    <bindings>
      <webHttpBinding>
        <binding name="httpsWebBinding">
          <security mode="Transport">
            <transport clientCredentialType="None" proxyCredentialType="None" />
          </security>
        </binding>
        <binding name="httpWebBinding">
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None" />
          </security>
        </binding>
      </webHttpBinding>
    </bindings>

    <diagnostics performanceCounters="Default" />

    <behaviors>   
      <serviceBehaviors>
        <behavior name="ZESDataServiceTypeBehaviors" >
          <serviceMetadata  httpGetEnabled="true" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true" />
          <!--<serviceAuthorization principalPermissionMode="UseWindowsGroups" />-->
          <!--<serviceAuthorization serviceAuthorizationManagerType=" ZES.MyServiceAuthorizationManager,  ZES" />-->
        </behavior>
      </serviceBehaviors>

      <endpointBehaviors>
        <behavior name="ZESDataAspNetAjaxBehavior">
          <webHttp />
          <enableWebScript />
        </behavior>
      </endpointBehaviors>
    </behaviors>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
         multipleSiteBindingsEnabled="true" />

    <services>
      <service behaviorConfiguration="ZESDataServiceTypeBehaviors"
                name="ZES.ZESData">
        <endpoint address=""
                                    behaviorConfiguration="ZESDataAspNetAjaxBehavior"
                                    binding="webHttpBinding"
                                    bindingConfiguration="httpsWebBinding"
                                    name="ZESData"
                                    contract=" ZES.IZESData" />
        <endpoint address=""
                  behaviorConfiguration="ZESDataAspNetAjaxBehavior"
                  binding="webHttpBinding"
                  bindingConfiguration="httpWebBinding"
                  name="ZESData"
                  contract="ZES.IZESData" />
        <endpoint address="mex"
                                    binding="mexHttpsBinding"                                   name="mex"                                  contract="IMetadataExchange" />
      </service>
    </services>
  </system.serviceModel>

  <location>
    <system.web>
      <authorization>
        <allow roles="ZES_r"/>
        <allow roles="ZES_rw"/>
        <deny users="*"/>
      </authorization>
    </system.web>
  </location>
  <location path="Error">
    <system.web>
      <authorization>
        <allow users="?"/>
      </authorization>
    </system.web>
  </location>
  <location path="Default.aspx">
    <system.web>
      <authorization>
        <allow roles="ZES_r"/>
        <allow roles="ZES_rw"/>
        <deny users="*"/>
      </authorization>
    </system.web>
  </location>
  <location path="Images">
    <system.web>
      <authorization>
        <allow users="*"/>
      </authorization>
    </system.web>
  </location>
</configuration>

我又一次找到了答案...... 在这里询问有助于找到解决方案,在其他人的帮助下并且没有 :-) 但也许它可以帮助别人......

如问题中所述,我没有尝试禁用匿名访问,因为我遇到了其他错误。

试图解决这个错误找到了答案。

我的绑定错误: (留下旧的作为评论)

<bindings>
  <webHttpBinding>
    <binding name="httpsWebBinding">
      <security mode="Transport">
        <!-- <transport clientCredentialType="None" proxyCredentialType="None" /> -->
        <transport clientCredentialType="Windows" proxyCredentialType="Windows" />
      </security>
    </binding>
    <binding name="httpWebBinding">
      <security mode="None">
        <!-- <transport clientCredentialType="None" proxyCredentialType="None" /> -->
        <transport clientCredentialType="Windows" proxyCredentialType="Windows" />
      </security>
    </binding>
  </webHttpBinding>
</bindings> 

现在

    [PrincipalPermission(SecurityAction.Demand, Role = "rdm-WEB-Reas_rw")]
    public String SetBoxPosition(PostBoxData postBoxData)

几乎按预期工作,只是我得到 "accepted" 而不是 "Not Allowed" 或类似的,当使用没有权限写入的用户时。

我从一个示例中复制了绑定以在您的网站上启用 https,这就是从网上复制和粘贴代码的结果,您不完全理解:-)

感谢阅读,如果您喜欢我的回答,请给我投票。我真的很想发表评论:-)