AdminService Init (Prototyp)

This commit is contained in:
2025-02-20 18:39:11 +01:00
parent 18d1ea2215
commit a6bff2d8b0
15 changed files with 381 additions and 17 deletions

1
Host/AdminService.svc Normal file
View File

@@ -0,0 +1 @@
<%@ ServiceHost Language="C#" Debug="true" Service="BeWo.Service.ServiceImplementations.AdminServiceImp" %>

View File

@@ -168,6 +168,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Content Include="AdminService.svc" />
<Content Include="GkvAccountingService.svc" />
<Content Include="Admin.aspx" />
<Content Include="AnalysisService.svc" />

View File

@@ -113,25 +113,16 @@
<requestLimits maxQueryString="65536" maxUrl="65536" />
</requestFiltering>
</security>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol>
</system.webServer>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="TransportSecurity" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="None">
<transport clientCredentialType="None" />
</security>
<readerQuotas maxStringContentLength="2147483647" />
</binding>
<binding name="TransportSecurityStreaming" maxBufferSize="65536" maxReceivedMessageSize="2147483647" messageEncoding="Text" transferMode="StreamedRequest">
<security mode="None">
<transport clientCredentialType="None" />
</security>
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<system.serviceModel>
<services>
<service behaviorConfiguration="returnFaults" name="BeWo.Service.ServiceImplementations.EmployeeServiceImp">
<endpoint behaviorConfiguration="SecurityAndSessionBehavior" binding="basicHttpBinding" bindingConfiguration="TransportSecurity" name="EmployeeServiceEndpoint" contract="BeWo.Service.ServiceContracts.IEmployeeService" />
@@ -184,7 +175,34 @@
<service behaviorConfiguration="returnFaults" name="BeWo.Service.ServiceImplementations.EnumTranslationServiceImp">
<endpoint behaviorConfiguration="SecurityAndSessionBehavior" binding="basicHttpBinding" bindingConfiguration="TransportSecurity" name="EnumTranslationServiceEndpoint" contract="BeWo.Service.ServiceContracts.IEnumTranslationService" />
</service>
<service behaviorConfiguration="returnFaults" name="BeWo.Service.ServiceImplementations.AdminServiceImp">
<endpoint behaviorConfiguration="webHttpBehaviorConfig" binding="webHttpBinding" bindingConfiguration="webHttpBindingConfig" name="AdminServiceEndpoint" contract="BeWo.Service.ServiceContracts.IAdminService" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="TransportSecurity" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="None">
<transport clientCredentialType="None" />
</security>
<readerQuotas maxStringContentLength="2147483647" />
</binding>
<binding name="TransportSecurityStreaming" maxBufferSize="65536" maxReceivedMessageSize="2147483647" messageEncoding="Text" transferMode="StreamedRequest">
<security mode="None">
<transport clientCredentialType="None" />
</security>
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" />
</binding>
</basicHttpBinding>
<webHttpBinding>
<binding name="webHttpBindingConfig">
<!-- Optional: Maximale Nachrichten- und Puffergröße anpassen -->
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None" />
<!-- Für ungesicherte Verbindungen (HTTP) -->
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="SecurityBehavior">
@@ -197,6 +215,13 @@
<HibernateSessionExtension />
<SecurityExtension />
</behavior>
<behavior name="webHttpBehaviorConfig">
<!--wichtig: erst Mulittenancy dann session dann security!-->
<AdminSecurityExtension />
<AdminMultitenancyExtension />
<AdminHibernateSessionExtension />
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="returnFaults">
@@ -212,11 +237,15 @@
<add name="MultitenancyExtension" type="BeWo.Service.Multitenancy.MultitenancyBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
<add name="SecurityExtension" type="BeWo.Service.Security.SecurityBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
<add name="HibernateSessionExtension" type="BeWo.Service.UnitOfWork.HibernateSessionBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
<add name="AdminMultitenancyExtension" type="BeWo.Service.ServiceBehavior.AdminMultitenancyBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
<add name="AdminSecurityExtension" type="BeWo.Service.ServiceBehavior.AdminSecurityBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
<add name="AdminHibernateSessionExtension" type="BeWo.Service.ServiceBehavior.AdminHibernateBehaviorExtension, BeWo.Service, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
</system.serviceModel>
<!-- <> <> <> Appsettings <> <> <> -->
<appSettings>
<add key="AdminServiceIPAddress" value="::1" />
<add key="SendMailOnError" value="false" />
<add key="SmptServer" value="mail.ownsoft.de" />
<add key="SmtpUser" value="bewoplaner.support@ownsoft.de" />

View File

@@ -191,6 +191,7 @@
<Reference Include="System.ServiceModel">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="System.ServiceModel.Web" />
<Reference Include="System.Text.Encoding.CodePages, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Encoding.CodePages.5.0.0\lib\net461\System.Text.Encoding.CodePages.dll</HintPath>
</Reference>
@@ -478,8 +479,18 @@
<Compile Include="Security\SecurityContextInitializer.cs" />
<Compile Include="Security\Right2Methods.cs" />
<Compile Include="Security\SecurityUtils.cs" />
<Compile Include="ServiceBehavior\AdminHibernateBehavior.cs" />
<Compile Include="ServiceBehavior\AdminHibernateBehaviorExtension.cs" />
<Compile Include="ServiceBehavior\AdminHibernateContextInitializer.cs" />
<Compile Include="ServiceBehavior\AdminMultitenancyBehavior.cs" />
<Compile Include="ServiceBehavior\AdminMultitenancyBehaviorExtension.cs" />
<Compile Include="ServiceBehavior\AdminMultitenancyContextInitializer.cs" />
<Compile Include="ServiceBehavior\AdminSecurityBehavior.cs" />
<Compile Include="ServiceBehavior\AdminSecurityBehaviorExtension.cs" />
<Compile Include="ServiceBehavior\AdminServiceMessageInspector.cs" />
<Compile Include="ServiceContracts\BeWoFault.cs" />
<Compile Include="ServiceContracts\IAccountingService.cs" />
<Compile Include="ServiceContracts\IAdminService.cs" />
<Compile Include="ServiceContracts\IAnalysisService.cs" />
<Compile Include="ServiceContracts\IGkvAccountingService.cs" />
<Compile Include="ServiceContracts\IMailService.cs" />
@@ -492,6 +503,7 @@
<Compile Include="ServiceContracts\IStreamingService.cs" />
<Compile Include="ServiceContracts\IResourceService.cs" />
<Compile Include="ServiceImplementations\AccountingServiceImp.cs" />
<Compile Include="ServiceImplementations\AdminServiceImp.cs" />
<Compile Include="ServiceImplementations\AnalysisServiceImp.cs" />
<Compile Include="ServiceImplementations\GkvAccountingServiceImp.cs" />
<Compile Include="ServiceImplementations\MailServiceImp.cs" />

View File

@@ -0,0 +1,35 @@
using BeWo.Service.UnitOfWork;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Text;
using System.Threading.Tasks;
namespace BeWo.Service.ServiceBehavior
{
public class AdminHibernateBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
foreach (DispatchOperation iOperation in endpointDispatcher.DispatchRuntime.Operations)
{
iOperation.CallContextInitializers.Add(new AdminHibernateContextInitializer());
}
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
}

View File

@@ -0,0 +1,20 @@
using BeWo.Service.UnitOfWork;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Configuration;
using System.Text;
using System.Threading.Tasks;
namespace BeWo.Service.ServiceBehavior
{
public class AdminHibernateBehaviorExtension : BehaviorExtensionElement
{
public override Type BehaviorType => typeof(AdminHibernateBehavior);
protected override object CreateBehavior()
{
return new AdminHibernateBehavior();
}
}
}

View File

@@ -0,0 +1,25 @@
using BeWo.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Text;
using System.Threading.Tasks;
namespace BeWo.Service.ServiceBehavior
{
public class AdminHibernateContextInitializer : ICallContextInitializer
{
public void AfterInvoke(object pCorrelationState)
{
}
public object BeforeInvoke(InstanceContext pInstanceContext, IClientChannel pChannel, Message pMessage)
{
return null;
}
}
}

View File

@@ -0,0 +1,36 @@
using BeWo.Service.Multitenancy;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Text;
using System.Threading.Tasks;
namespace BeWo.Service.ServiceBehavior
{
public class AdminMultitenancyBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
throw new NotImplementedException("This is a server behavior only");
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
foreach (DispatchOperation iOperation in endpointDispatcher.DispatchRuntime.Operations)
{
iOperation.CallContextInitializers.Add(new AdminMultitenancyContextInitializer());
}
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Configuration;
using System.Text;
using System.Threading.Tasks;
namespace BeWo.Service.ServiceBehavior
{
public class AdminMultitenancyBehaviorExtension : BehaviorExtensionElement
{
public override Type BehaviorType => typeof(AdminMultitenancyBehavior);
protected override object CreateBehavior()
{
return new AdminMultitenancyBehavior();
}
}
}

View File

@@ -0,0 +1,55 @@
using BeWo.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Channels;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Xml;
using System.ServiceModel.Dispatcher;
using BeWo.Service.Core;
namespace BeWo.Service.ServiceBehavior
{
public class AdminMultitenancyContextInitializer : ICallContextInitializer
{
public void AfterInvoke(object pCorrelationState)
{
if (pCorrelationState is MultitenancyOperationContextExt)
{
OperationContext.Current.Extensions.Remove((MultitenancyOperationContextExt)pCorrelationState);
}
}
public object BeforeInvoke(InstanceContext pInstanceContext, IClientChannel pChannel, Message pMessage)
{
string lTenant = null;
try
{
if (pMessage.Properties?.Via is Uri uri)
{
var query = HttpUtility.ParseQueryString(uri.Query);
var tenant = query["tenant"];
lTenant = tenant;
}
if (!string.IsNullOrEmpty(lTenant))
{
var lExt = new MultitenancyOperationContextExt { Tenant = lTenant };
OperationContext.Current.Extensions.Add(lExt);
return lExt;
}
return null;
}
catch (Exception e)
{
throw Utils.CreateBeWoFaultException(e);
}
}
}
}

View File

@@ -0,0 +1,39 @@
using BeWo.Data;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Text;
using System.Threading.Tasks;
namespace BeWo.Service.ServiceBehavior
{
public class AdminSecurityBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
// Keine zusätzlichen Bindungsparameter erforderlich
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
// Verhalten für Clients - hier nicht benötigt
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
// Füge einen Message Inspector hinzu, um eingehende Requests zu überprüfen
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new AdminServiceMessageInspector());
}
public void Validate(ServiceEndpoint endpoint)
{
// Optional: Endpunktvalidierung (falls erforderlich)
}
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.ServiceModel.Configuration;
namespace BeWo.Service.ServiceBehavior
{
public class AdminSecurityBehaviorExtension : BehaviorExtensionElement
{
public override Type BehaviorType => typeof(AdminSecurityBehavior);
protected override object CreateBehavior()
{
return new AdminSecurityBehavior();
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using BeWo.Data;
namespace BeWo.Service.ServiceBehavior
{
public class AdminServiceMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
// Hole die erlaubte IP aus den appSettings
string allowedIP = ConfigurationManager.AppSettings["AdminServiceIPAddress"];
// Extrahiere die RemoteEndpoint-IP-Adresse
string remoteIP = request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name)
? ((RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessageProperty.Name]).Address
: null;
// Vergleiche die IPs
if (remoteIP == null || !string.Equals(remoteIP, allowedIP, StringComparison.OrdinalIgnoreCase))
{
throw new UnauthorizedAccessException($"Zugriff verweigert. Remote IP ({remoteIP ?? "Unbekannt"}) ist nicht erlaubt.");
}
return null; // Keine Zustandsinformationen erforderlich
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
// Keine zusätzliche Logik erforderlich vor dem Senden der Antwort
}
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Threading.Tasks;
namespace BeWo.Service.ServiceContracts
{
[ServiceContract]
public interface IAdminService
{
[OperationContract]
[WebGet(UriTemplate = "/Test")]
string Test();
}
}

View File

@@ -0,0 +1,19 @@
using BeWo.Service.ServiceContracts;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
namespace BeWo.Service.ServiceImplementations
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)]
public class AdminServiceImp : IAdminService
{
public string Test()
{
return "Test erfolgreich!";
}
}
}