Cross Domain Policy - wcf

I am working with a Silvelright App that consumes a WCF service, I have placed a crossdomain and clientaccesspolicy xml's in the wwwroot of the IIS as well as in the application folder!
yet when the client communicates with the service, it throws an error saying;
An error occurred while trying to make a request to URI ‘http://localhost:1528/MyService.svc’. This could be due to attempting to access a service in a cross-domain way without a proper cross-domain policy in place, or a policy that is unsuitable for SOAP services. You may need to contact the owner of the service to publish a ……
Please help!
Thanks

The clientaccesspolicy.xml needs to be on the same port as your service. It needs to be located at http://localhost:1528/clientaccesspolicy.xml
If you are self hosting the WCF service then you need to host the clientaccesspolicy.xml from within your WCF service. The easiest way I've found to do this is to add a separate service contract that provides an HTTP GET of the clientaccesspolicy.xml.
[ServiceContract()]
public class PolicyRetriever
{
[OperationContract, WebGet(UriTemplate = "/clientaccesspolicy.xml")]
public Stream GetSilverlightPolicy()
{
string result = #"<?xml version=""1.0"" encoding=""utf-8""?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers=""*"">
<domain uri=""*""/>
</allow-from>
<grant-to>
<resource path=""/"" include-subpaths=""true""/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>";
if (System.ServiceModel.Web.WebOperationContext.Current != null)
{
System.ServiceModel.Web.WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
}
return new MemoryStream(Encoding.UTF8.GetBytes(result));
}
}

Related

Consume soap Service in Apache Camel

i want to consume soap web serivce in apache camel using Java DSL.Any way without CXF.i have already try using CXF with spring.
Here is a simple example that used only camel http without cxf. If you need to perform some modifications of SOAP request string you can just change "constant" to something like "spel".
<setBody><constant><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<MyAction>
<myparam>ABC</myparam>
</MyAction>
</soapenv:Body>
</soapenv:Envelope>]]></constant></setBody>
<setHeader headerName="SOAPAction"><constant>MySOAPAction</constant></setHeader>
<setHeader headerName="CamelHttpMethod"><constant>POST</constant></setHeader>
<setHeader headerName="Content-Type"><constant>text/xml;charset=UTF-8</constant></setHeader>
<to uri="http://myserver:1234" />
Same with Java DSL
public class MyRouteBuilder extends RouteBuilder {
public void configure() {
from("direct:start")
.setBody(constant("")) // String SOAP content from XML example
.setHeader("SOAPAction", constant("MySOAPAction"))
.setHeader("CamelHttpMethod", constant("POST"))
.setHeader("Content-Type", constant("text/xml;charset=UTF-8"))
.to("http://myserver:1234")
.log("SOAP service called"); // Here you can process service response
}
}

Cross-domain error Silverlight + WCF

I have read most of the topics covering cross-domain error and still cannot get it working. Within the website, I load Silverlight module which communicates with WCF Webservice. On localhost, it works fine, no error occurred.
I have Webservice hosted on http://localhost:50283 and in the same folder that port 50283 refers to I have clientaccesspolicy.xml located which looks as follows
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
I placed clientaccesspolicy.XML hardly everywhere including \wwwroot but that brought no effect anyway. I can access clientaccesspolicy.xml both on local and on a different computer within the same network (http://computerIP:50283/clientaccesspolicy.xml displays content). I tried to intercept error in order to find out some more details about error's nature but fiddler does not enlist any error, the only browser does. Literally, I tried everything and still no change. Has anyone faced a similar issue and could provide some hints where I should seek for a solution?
I ran into similar topic with no solution as well, alas
Silverlight-to-WCF cross-domain exception, but clientaccesspolicy.xml is being read successfully
I remember running into this many years ago and solving it a bit differently, namely with a behavior. Consider the following:
using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.Xml;
internal class CrossDomainServiceBehavior : BehaviorExtensionElement, IEndpointBehavior
{
private ServiceHost serviceHost;
public override Type BehaviorType
{
get { return typeof(CrossDomainServiceBehavior); }
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
if (serviceHost == null)
{
serviceHost = new ServiceHost(typeof(CrossDomainPolicyService));
string address = new Uri(endpoint.Address.Uri, "/").ToString();
ServiceEndpoint crossDomainEndpoint = serviceHost.AddServiceEndpoint(typeof(ICrossDomainPolicyService), new WebHttpBinding(), address);
crossDomainEndpoint.Behaviors.Add(new WebHttpBehavior());
serviceHost.Open();
}
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
protected override object CreateBehavior()
{
return new CrossDomainServiceBehavior();
}
}
internal class CrossDomainPolicyService : ICrossDomainPolicyService
{
public Message ProvideClientAccessPolicyFile()
{
XmlReader xmlReader = CreateClientAccessXml();
return Message.CreateMessage(MessageVersion.None, string.Empty, xmlReader);
}
public Message ProvideCrossDomainPolicyFile()
{
XmlReader xmlReader = CreateCrossDomainXml();
return Message.CreateMessage(MessageVersion.None, string.Empty, xmlReader);
}
private static XmlReader CreateClientAccessXml()
{
TextReader reader = new StringReader(#"<?xml version='1.0' encoding='utf-8'?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers='*' >
<domain uri='*'/>
</allow-from>
<grant-to>
<resource path='/' include-subpaths='true'/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>");
return XmlReader.Create(reader);
}
private static XmlReader CreateCrossDomainXml()
{
TextReader reader = new StringReader(#"<?xml version='1.0'?>
<cross-domain-policy>
<allow-http-request-headers-from domain='*' headers='*'/>
</cross-domain-policy>");
return XmlReader.Create(reader);
}
}
The CrossDomainServiceBehavior needs to be added to the behaviors on your WCF service and it uses the CrossDomainPolicyService for dynamically adding the cross domain policy. This prevents you from having to add the cross domain file to the website itself.
Adding the behavior from code (for example with self hosted services):
endPoint.Behaviors.Add(new CrossDomainServiceBehavior());
Or in case of WCF definitions in config:
For the sake of this example I will assume the CrossDomainServiceBehavior is in the namespace Services.CrossDomainServiceBehavior and the assembly it is located in is version 1.0.0.0 with a neutral culture. It also assumes you have a binding on your service declaration called webHttp.
Registering the behavior:
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="CrossDomainServiceBehavior" type="Services.CrossDomainServiceBehavior, CrossDomainServiceBehavior.AssemblyName, Version=1.0.0.0, Culture=neutral" />
</behaviorExtensions>
</extensions>
Declare the behavior:
<behaviors>
<endpointBehaviors>
<behavior name="CrossDomainServiceBehavior">
<webHttp/>
<CrossDomainServiceBehavior/>
</behavior>
</endpointBehaviors>
<behaviors>
Add the behavior to the binding (here as example one called webHttp):
<bindings>
<webHttpBinding>
<binding name="webHttp"
maxReceivedMessageSize="20000000" >
<security mode="None">
<transport clientCredentialType = "None"/>
</security>
</binding>
<CrossDomainServiceBehavior />
</webHttpBinding>
</bindings>
Finally, add the behavior to your service endpoint, here in example one that implements ISomeService:
<endpoint address="" binding="webHttpBinding" contract="Services.ISomeService" bindingConfiguration="webHttp" behaviorConfiguration="CrossDomainServiceBehavior "/>
Not sure if it has to do anything with it, but I have a similar setup and my clientaccesspolicy.xml looks a bit different.
<?xml version="1.0" encoding="utf-8" ?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="SOAPAction">
<domain uri="http://*"/>
<domain uri="https://*" />
</allow-from>
<grant-to>
<resource include-subpaths="true" path="/"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
Especially the splitting of http and https adresses is different.
Besides that you are trying to do this with a non-default port, have you tried it on the default port 80? oh and on the production environment those *'s are replaced with the actual domain name.

Handle Fault string message if end point not exits in wsdl

I am getting the below exception when trying to call service from SOAPUI that is fine
because message part element dose not exits in wsdl.
But I want to handle in proper way in CXF web service and send proper fault string instead of below message ex: "Bad Request"
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<Action xmlns="http://www.w3.org/2005/08/addressing"/>
<MessageID xmlns="http://www.w3.org/2005/08/addressing">urn:uuid:109a84f4-373d-4406-9087-82bd58bea394</MessageID>
<To xmlns="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/anonymous</To>
<RelatesTo xmlns="http://www.w3.org/2005/08/addressing">uuid:3dcf9e26-20fc-4c93-bc01-8ca9ab1ae2eb</RelatesTo>
</soap:Header>
<soap:Body>
<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring>Message part Reservation was not recognized. (Does it exist in service WSDL?)</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
Does any one know in cxf where I can handle in proper way ?
You can solve this problem by consuming the web service from a client application. Everywhere you need to consume the WS, should put a BindingProvider to the port. This example is a method of:
...
import javax.xml.ws.BindingProvider;
public class WSClient {
public String getUserName(int userCode) {
WebServiceAuth ss = new WebServiceAuth();
IWebServiceAuth port = ss.getPort(IWebServiceAuth.class);
BindingProvider bindingProvider = (BindingProvider) port;
bindingProvider
.getRequestContext()
.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
"http://localhost:8081/WebServiceAuth/WSAuth");
return port.getUserName(userCode);
}
}
In this case you need to put your service's address into the BindingProvider.

JAX-WS ws-security UsernameToken authorization on server

I have created a web service in netbeans with METRO. I modified my web service wsit config for using Usernametoken authentication (without encryption).
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" name="NewWebService" targetNamespace="http://test.org/" xmlns:tns="http://test.org/" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:fi="http://java.sun.com/xml/ns/wsit/2006/09/policy/fastinfoset/service" xmlns:tcp="http://java.sun.com/xml/ns/wsit/2006/09/policy/soaptcp/service" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702" xmlns:sc="http://schemas.sun.com/2006/03/wss/server" xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy"
>
<message name="hello"/>
<message name="helloResponse"/>
<portType name="NewWebService">
<operation name="hello">
<input message="tns:hello"/>
<output message="tns:helloResponse"/>
</operation>
</portType>
<binding name="NewWebServicePortBinding" type="tns:NewWebService">
<wsp:PolicyReference xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" URI="#UsernameToken"/>
<operation name="hello">
<input></input>
<output></output>
</operation>
</binding>
<service name="NewWebService">
<port name="NewWebServicePort" binding="tns:NewWebServicePortBinding"/>
</service>
<!-- Policy for Username Token with plaintext password, sent from client to server only -->
<wsp:Policy wsu:Id="UsernameToken" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SupportingTokens xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken=".../IncludeToken/AlwaysToRecipient"/>
</wsp:Policy>
</sp:SupportingTokens>
<wsss:ValidatorConfiguration wspp:visibility="private" xmlns:wsss="http://schemas.sun.com/2006/03/wss/server" xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy">
<wsss:Validator name="usernameValidator" classname="org.test.MyAuth"/>
</wsss:ValidatorConfiguration>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
</definitions>
My PasswordValidator
package org.test;
import com.sun.xml.wss.impl.callback.PasswordValidationCallback;
import com.sun.xml.wss.impl.callback.PasswordValidationCallback.PasswordValidationException;
import com.sun.xml.wss.impl.callback.PasswordValidationCallback.Request;
public class MyAuth implements PasswordValidationCallback.PasswordValidator
{
#Override
public boolean validate(Request request) throws PasswordValidationException {
PasswordValidationCallback.PlainTextPasswordRequest ptreq
= (PasswordValidationCallback.PlainTextPasswordRequest)request;
//Database query
return CheckUserInDateBase(ptreq.getPassword(), ptreq.getUsername());
}
}
Now i need authorize user with his username and password and check his role (every method of web service has annotation RolesAllowed). I have created SOAP handler for my web service where I trying to get username and password from soap headers, but header doesnt contains this information (when i get this header in handler).
Actually SOAP message looks like
<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<S:Header>
<macAddress xmlns="http://ws.mkyong.com/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:actor="http://schemas.xmlsoap.org/soap/actor/next">F8-D1-11-01-36-20</macAddress>
<wsse:Security S:mustUnderstand="1">
<wsse:UsernameToken xmlns:ns15="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity" xmlns:ns14="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512" xmlns:ns13="http://www.w3.org/2003/05/soap-envelope" wsu:Id="uuid_48e60f1c-aea9-4bcc-897f-ef661fe2895b">
<wsse:Username>myusername</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">mypass</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</S:Header>
<S:Body>
<ns2:hello xmlns:ns2="http://test.org/">
<name>aaaa</name>
</ns2:hello>
</S:Body>
</S:Envelope>
When I trying to extract header's child elements I'm getting only macAddress header (my custom header)
#Override
public boolean handleMessage(SOAPMessageContext context) {
Iterator i = context.getMessage().getSOAPPart().getEnvelope().getHeader().getChildElements();
return true;
}
So. How can I access to wssecurity headers? Or maybe has another way to check user role before execution web service method?
Instead of checking at your validator, store the username and password using ThreadLocal then apply your authentication roles within the service implementation as below. In my case, I used this approach to throw a custom exception.
My Validator:
/**
* #author SaudAlajmi
*
*/
public class PasswordValidator implements PasswordValidationCallback.PasswordValidator {
/* I used this approach because they need to throw a custom exception in case of authentication failure, as far as I know there is no such way
* to do it especially since the validator does not have access to the WebServiceContext, but this way and it is safe because every thread has
* it is own copy and that's why I used ThreadLocal;
*/
private static final ThreadLocal<String> username = new ThreadLocal<String>();
private static final ThreadLocal<String> password = new ThreadLocal<String>();
public boolean validate(Request request) throws PasswordValidationException {
PasswordValidationCallback.PlainTextPasswordRequest ptreq = (PasswordValidationCallback.PlainTextPasswordRequest) request;
password.set(ptreq.getPassword());
username.set(ptreq.getUsername());
return true;
}
public static String getUsername() {
String user = username.get();
username.remove();
return user;
}
public static String getPassword() {
String pwd= password.get();
password.remove();
return pwd;
}
}
My Service Impl:
String username = PasswordValidator.getUsername();
String password = PasswordValidator.getPassword();
if(username == null || !"test".equals(username) || password == null ||!"test".equals(password)){
faultInfo = new CommonErrorStructure();
faultInfo.setCode("KFSH000401");
faultInfo.setErrorText("Username/Password is incorrect");
faultInfo.setRaisedBy("PatientRecordService");
throw new GetPatientRecordError("Authentication Failure", faultInfo);
}
Reference:
Retrieve plaintext WS-Security password at service endpoint with Metro + WSIT?

Silverlight WCF issue with cross-domain policy file

Ive seen a number of threads on this issue but none have worked for me. I have a simple silverlight application. I consume a WCF service. When I call a method GetOrderList from the service I get the following error:
An error occurred while trying to make a request to URI 'https://testserver2.mydomain.org/ORDERNET/WCFServices/OrderService/OrderService.svc'. This could be due to attempting to access a service in a cross-domain way without a proper cross-domain policy in place, or a policy that is unsuitable for SOAP services. You may need to contact the owner of the service to publish a cross-domain policy file and to ensure it allows SOAP-related HTTP headers to be sent. This error may also be caused by using internal types in the web service proxy without using the InternalsVisibleToAttribute attribute. Please see the inner exception for more details.
Here is my code:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
ServiceReference1.ServiceClient sc = new ServiceReference1.ServiceClient();
sc.GetOrderListAsync("testuser");
sc.GetOrderListCompleted += new EventHandler<ServiceReference1.GetOrderListCompletedEventArgs>(sc_GetOrderListCompleted);
}
void sc_GetOrderListCompleted(object sender, ServiceReference1.GetOrderListCompletedEventArgs e)
{
var RESULT = e.Result;
}
}
This is my client access policy file that I put on my wwwroot:
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
When I run fiddler, it finds the "clientaccesspolicy.xml" with a 200 OK (text/xml) so I know is finding the file.
What could be the issue? Do I have an invalid policy file? If I create a console application and consume the service, I can call the method with thno problem.
Any ideas?
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="SOAPAction">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
Silverlight Cross Domain Web Service Access Error - This could be due to attempting to access a service in a cross-domain way without a proper cross-domain policy in place
thanks.....
I had similar issue but with service having http protocol, which was solved using .clientconfig file.
I notice you are using HTTPS (https://testserver2.mydomain.org/ORDERNET/WCFServices/OrderService/OrderService.svc)
Have you tried explicitly adding a https://* uri to your cross domain policy file:
<domain uri="https://*"/>
If you need to support http, then add both:
<domain uri="http://*"/>
<domain uri="https://*"/>