I am running blazeds on the server side. I would like to filter http requests using an http header. My goal is to send extra parameters to the server without changing the signatures of my blazeds services.
On the client side, I am using Flex RemoteObject methods.
With Flex WebService components, it is possible to set an http header using the property httpHeaders. I have not found anything similar on the RemoteObject class...
I couldnt modify http request from flex, instead I can add custom headers to the mx.messaging.messages.IMessage that RemoteObject sends to the server and there, extending flex.messaging.services.remoting.adapters.JavaAdapter (used for accessing Spring beans), it's posible to read the header parameters and put them into the HTTPRequest.
In the flex part, I had to extend mx.rpc.AsyncRequest:
declares a new property "header" and overwrites invoke method that checks if there is a not null value for set the msg.headers.
and mx.rpc.remoting.mxml.RemoteObject:
the constructor creates a new instance of our custom AsyncRequest and overwrite old AsyncRequest and it defines a setHeaders method that set the argument to the custom AsyncRequest.
com.asfusion.mate.actions.builders.RemoteObjectInvoker (extra :P):
this one reads the param declared in the Mate's map RemoteObjectInvoker and puts in the RemoteObject header.
I hope it will be understandable (with my apache english xDDD)
Bye. Agur!
This worked for me using BlazeDS and Spring-Flex 1.5.2
Flex:
use namespace mx_internal;
var service:RemoteObject = new RemoteObject(destination);
var operation:Operation = service[functionName];
operation.asyncRequest.defaultHeaders = {company:'company'};
var token:AsyncToken = operation.send();
Java Spring-Flex:
public class FlexJavaCustomAdapter extends JavaAdapter{
#Override
public Object invoke(Message message) {
String locale = (String) message.getHeader("com.foo.locale");
return super.invoke(message);
}
}
dispatcher-servlet.xml
<bean id="customAdapter" class="org.springframework.flex.core.ManageableComponentFactoryBean">
<constructor-arg value="com.codefish.model.flex.FlexJavaCustomAdapter"/>
</bean>
<flex:message-broker id="_messageBroker" services-config-path="classpath*:/com/codefish/resources/spring/services-config.xml" >
<flex:remoting-service default-adapter-id="customAdapter"
default-channels="my-amf, my-secure-amf" />
</flex:message-broker>
</bean>
RemoteObject uses AMF as the data channel, and is managed in a completely different way than HttpService or WebService (which use Http).
What you can do, is call setCredentials(username,password) and then capture this on the server side using the FlexLoginCommand (either the standard one for your container, or derive your own).
Lookup setCredentials and how you should handle this on both sides (client and server).
I have similar problem, and I afraid there is no simple way to set HTTP header when using AMF. But I've designed following solution.
Flex uses HTTP to transfer AMF, but invokes it through browser interfaces, this allows you to set cookie. Just in document containing application invoke following JavaScript
document.cookie="clientVersion=1.0;expires=2100-01-01;path=/";
Browser should transfer it to server, and you can filter (problem will be if the user will have cookies turned off).
Much more you can invoke JavaScript functions from Flex (more is here: http://livedocs.adobe.com/flex/3/html/help.html?content=passingarguments_4.html).
You might be trying to re-invent the wheel. Is there a reason you can't use the standard HTTP(s) authentication?
A reason I was thinking too to use http headers was for the server to be able to 'recognize' the flex client in the a context of service versionning.
On the server I can always build an indirection/proxy that would allow the different clients to only use 1 end point and route to the right adapter depending on the client version.
The question is on the client side. How would the server identify the flex client token or 'version'. One way is certainly via authentication. But, assuming there is not authentication involved?
We recently run into the same issue and this is how we added our custom headers without creating a subclass:
var operation:AbstractOperation = _remoteSession.getOperation('myRemoteOperation');
var async:AsyncRequest = operation.mx_internal::asyncRequest;
async.defaultHeaders = {my_header:'my_value'};
The AsyncRequest object is actually accessible via the operation object via the mx_internal namespace.
You can debug the $GLOBALS in PHP to see that.
I think this is in the
$GLOBALS['HTTP_RAW_POST_DATA'];
or you can simple do
file_get_contents('php://input');
Related
I have a Spring Boot application, that is using Spring Security with OAuth 2.0. Currently, it is operating against an Authentication Server based on Spring Example code. However, running our own Auth Server has always been a short-term target to facilitate development, not a long-term goal. We have been using the authorization_code grant type and would like to continue using that, irrespective of the Auth Server implementation.
I am attempting to make changes to use OAuth 2.0 Endpoints in Azure Active Directory, to behave as our Authentication Server. So far, I have a successful call to the /authorize endpoint. But the call to get the /token fails with an invalid request error. I can see the requests going out.
It appears that parameters that Azure states as mandatory are not being populated in the POST request. Looking at the Azure doco, it expects the client_id to be defined in the body of the message posted to the endpoint, and that is not added, by default, by Spring.
Can anyone point me in the right direction for how I can add fields to the Form Map that is used when constructing the Access Token request? I can see where the AccessTokenRequest object is being setup in OAuth2ClientConfiguration....
#Bean
#Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
protected AccessTokenRequest accessTokenRequest(#Value("#{request.parameterMap}")
Map<String, String[]> parameters, #Value("#{request.getAttribute('currentUri')}")
String currentUri) {
DefaultAccessTokenRequest request = new DefaultAccessTokenRequest(parameters);
request.setCurrentUri(currentUri);
return request;
}
Should I be trying to define the map in a request.parameterMap spring property? If so, I'm not too sure how that works.
Or should I be using one of the interfaces defined in the AuthorizationServerConfigurerAdapter class?
I have the information to include when sending the AccessTokenRequest, I just don't know the best way to configure Spring to include it? Thanks for any help.
Actually, I found this out. I needed to change the client authentication scheme. Simply adding the following to my application properties added the client_id to the form....
security.oauth2.client.clientAuthenticationScheme=form
If you're using yaml, then yaml-ize it. Thank you Spring!
At my workplace we are in the process of upgrading our Time and Attendance setup. Currently, we have physical terminals that employees use to check in and check out. These terminal communicate to a 3rd party T&A system via web service calls.
About the T&A web service:
Hosted on IIS 6
Communication is with WCF over HTTP
We're only interested in one of the exposed methods (let's call it Beep())
What I need to do:
Leave the original T&A system in place, untouched
Write a custom service that also reacts to calls to Beep()
So, essentially, I need to piggy-back on all the calls to Beep(), but I'm not sure what the best approach is.
What has been considered already:
Write a custom webservice that implements the exact same same contract as the T&A service and direct all the terminals to that custom service. The idea being that I can then invoke the original T&A service from my custom service, as well as applying any other logic required.
This seems overly invasive to me, and seems needlessly risky. We want to leave the original system as unmodified as possible.
Write a custom HTTP Handler to intercept calls to the original T&A service.
We've actually already done something like this in house, but our implementation takes the original HttpRequest, extracts the contents, invokes a custom service, and finally create a new HttpRequest based on the original request so that the original web service call to Beep() is made.
What I don't like about this approach is that the original HttpRequest is lost. Yes, a second, supposedly identical, request is created, but I don't know enough about HttpRequests to guarantee this is safe.
I prefer option 2, but it's still not perfect. Ideally we wouldn't need to destroy the original HttpRequest. Does anyone know if this is possible?
If not, can anyone suggest another way of doing this? Can IIS be configured to fork requests to two destinations?
Thanks
UPDATE #1
I have found a solution (documented here), but I'm still open to other options.
UPDATE #2
I like flup's solution (and justification). He gets the bounty :) Thanks flup!
You can configure the web service to use a custom operation invoker, an IOperationInvoker.
WCF deserializes the original HTTP request as always, but instead of calling Beep() on the existing web service class, it will call your invoker instead. The invoker does its special thing, and then calls Beep() on the original service.
Advantage over implementing an IHTTPModule would be that all things HTTP are still handled by the original web service's configuration, unchanged. You fork off at a higher level of abstraction, namely on the web service's interface, at the Beep() method.
The nitty gritty of setting up a custom operation invoker without changing the existing service class (which makes it harder):
Implement a custom IOperationBehavior which sets the custom IOperationInvoker on the service's Beep() method in its ApplyDispatchBehavior method.
Implement a custom IEndpointBehavior which sets the custom IOperationBehavior in its ApplyDispatchBehavior method.
Put these two behaviors, with your IOperationInvoker, in a class library and add it to the existing service
Then configure the service to use the IEndpointBehavior.
See When and where to set a custom IOperationInvoker? and http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/17/wcf-extensibility-ioperationinvoker.aspx for the invoker bit.
See Custom Endpoint Behavior using Standard webHttpEndpoint on how to configure a custom endpoint.
Sounds actually like you want to integrate your system into an ESB pattern. Now the MS solution to the ESB problem is Biztalk. Biztalk is the thermonuclear warhead nut cracker in this case. You don't want Biztalk.
Check out the results here for lightweight alternatives
I have found a solution using a custom IHttpModule. See sample below:
using System;
using System.Text;
using System.Web;
namespace ForkHandles
{
public class ForkHandler : IHttpModule
{
public void Init(HttpApplication application)
{
application.BeginRequest += new EventHandler(application_BeginRequest);
}
void application_BeginRequest(object sender, EventArgs e)
{
var request = ((HttpApplication)sender).Request;
var bytes = new byte[request.InputStream.Length];
request.InputStream.Read(bytes, 0, bytes.Length);
request.InputStream.Position = 0;
var requestContent = Encoding.ASCII.GetString(bytes);
// vvv
// Apply my custom logic here, using the requestContent as input.
// ^^^
}
public void Dispose()
{
}
}
}
This will allow me to inspect the contents of a webservice request and react to it accordingly.
I'm open to other solutions that may be less invasive as this one will require changing the deployed 3rd party web service's configuration.
If you want to intercept the message to the T&A WCF service i would suggest using custom listener which can be plugged into the service call by making changes in the web.cofig.
This will be transparent.
Please look for WCF Extensibility – Message Inspectors.
system.diagnostics>
<sources>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="ServiceModelMessageLoggingListener">
<filter type=""/>
</add>
</listeners>
</source>
</sources>
</system.diagnostics>
Ive got a WCF service which has multiple web methods in it. I want to be able to intercept the request on all methods and look at the Ip address. Id rather not put the logic into a method call at the top of each called web method is there a way to intercept all calls to these methods from one place?
If it was a page I would write a base page object but im nout sure if there are events raised on a wcf call?
WCF allows you to implement interceptors that are added to the stack. See this link for an example. I´m not sure whether this allows you the extract the senders IP but I think it´s worth a try.
You can implement IDispatchMessageInspector and do something like this.
public object AfterReceiveRequest(ref Message request,
IClientChannel channel, InstanceContext instanceContext)
{
RemoteEndpointMessageProperty remoteEndpoint = request.Properties
[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
//remoteEndpoint.Address will give you the address.
return null;
}
You can use Custom Behaviors, they are part of WCF Extensibility features. Here's more information: Extending WCF with Custom Behaviors
There's a clever way to do this with the ServiceAuthorizationManager, and it's far easier than all the seriously hard work of the IDispatchMessageInspector.
Create a class in your WCF Service project like so:
public class MyServiceAuthorizationManager : ServiceAuthorizationManager
{
protected override bool CheckAccessCore(OperationContext operationContext)
{
string classMethod = operationContext.RequestContext.RequestMessage.Headers.Action;
if (classMethod.Contains("/transfer/Get"))
{
return true; // because someone is simply updating a client service reference
}
Console.WriteLine("Class Method Call: {0}",classMethod);
// do something with operationContext here as you need to inspect stuff
// return true if you want this class method call to succeed and go through
// return false if you want this class method to fail on the client
return true;
}
}
Then, in your service, right before your host.Open() call, add the link to MyServiceAuthorizationManager.
ServiceHost host = new ServiceHost(typeof(MyProject.Service1));
host.Authorization.ServiceAuthorizationManager = new MyServiceAuthorizationManager();
host.Open();
Now when you test your client connections, you'll notice that the console outputs what class method was called. You can also work against all the stuff in the operationContext object.
One way I use this is for a security header check. In my client, I add a header. Then, in the service, in this CheckAccessCore() call, I verify that this custom header exists. If it doesn't, then I return false. This is one more layer of protection that keeps the hackers out, and is great for the limited security in Named Pipes configurations too. If you're wanting to also do that, then click here for more information on how to add custom headers that automatically get sent on every client's method call on the service.
And note, among all this, I didn't have to mess with behaviors, claims, listeners, or message dispatches. I also didn't need to edit my WCF Configuration.
Note the string check for /transfer/Get above. This is important if you're doing header checks as a security mechanism like I was. If you don't have that condition and return true, then your WCF client IDE can't update its ServiceReference because the IDE doesn't know about that extra header (if you're adding a custom header and not specifying that header in the WCF client's app.config). Otherwise, you'll get an error The URI prefix is not recognized.
I have an https .net webservice. Invoking web methods using tools like soap UI works fine. I am unable to invoke the webmethod from flex. My WSDL loads up fine in flex.
On deployment my flex application and the webservice are on the same server. When use the machine url and access from within the server it works fine, but not when I use the https url for the flex application.
Eg - http://machinename/flex/flexApp.html works fine with https://publicname/wservice/ws.asmx but https://publicname/flex/flexapp.html fails to work.
I have the crossdomain policy in place with full access and also I have a valid SSL certificate on the server.
When I make the call from my local machine in debug mode I see the following in Fiddler-
The WSDL call goes fine and returns back correctly and the Protocol is shown as HTTPS where as the webmethod call following it shows the protocol as HTTP and returns back with the error -
I have been stuck on this for quite some time. Any help is greatly appreciated.
Thanks,
Nikhil.
Here is my Flex code that calls it:
//business delegate
public function BusinessDelegate(responder : IResponder):void
{
_responder = responder;
_service = ServiceLocator.getInstance().getService("sqlWebService");
_service.loadWSDL();
}
//Login User
public function Login(userId:String,password:String):void
{
var asyncToken:AsyncToken = _service.LoginUser(userId,password);
asyncToken.addResponder(_responder);
}
and the service locator has the following tag where I set the URL from outside as https://....
<mx:WebService
id="sqlWebService"
useProxy="false"
concurrency="multiple"
showBusyCursor="true"
wsdl="{Url}"/>
I finally was able to resolve this problem by replacing the code where I call the Flex WebService object with the specific generated classes for the webservice.
I generated classes for the webservice using Import WebService(WSDL) and was setting the url on the main class on run time as https://.....
and it works like a charm...and I see that in fiddler it shows me correctly going out as HTTPS instead of the HTTP.
Here is what helped me -
http://livedocs.adobe.com/flex/3/html/help.html?content=security2_15.html
Comment by nated.
Thanks Flextras.com for pointing me to right direction.
Resolved.
If using WCF service and WebService in Flex, use
service.svc?wsdl for HTTP and
service.svc/wsdl?wsdl for HTTPS,
I have a Tomcat service running on localhost:8080 and I have installed BlazeDS. I created and configured a simple hello world application like this...
package com.adobe.remoteobjects;
import java.util.Date;
public class RemoteServiceHandler {
public RemoteServiceHandler()
{
//This is required for the Blaze DS to instantiate the class
}
public String getResults(String name)
{
String result = “Hi ” + name + “, the time is : ” + new Date();
return result;
}
}
With what query string can I invoke RemoteServiceHandler to my Tomcat instance via just a browser? Something like... http://localhost:8080/blazeds/?xyz
Unfortunately you can't. First the requests (and responses) are encoded in AMF and second I believe they have to be POSTs. If you dig through the BlazeDS source code and the Flex SDK's RPC library you can probably figure out what it's sending. But AFAIK this hasn't been documented anywhere else.
I think that AMFX (which is AMF in XML) will work for you, using HTTPChannel instead of AMFChannel.
From http://livedocs.adobe.com/blazeds/1/blazeds_devguide/help.html?content=lcarch_2.html#1073189, Channels and channel sets:
Flex clients can use different channel
types such as the AMFChannel and
HTTPChannel. Channel selection depends
on a number of factors, including the
type of application you are building.
If non-binary data transfer is
required, you would use the
HTTPChannel, which uses a non-binary
format called AMFX (AMF in XML). For
more information about channels, see
Channels and endpoints.
This way you can use simple netcat to send the request.
Not sure how authentication will be handled though, you will probably need do a login using Flash, extract the authentication cookie and then submit it as part of your request.
Please update this thread once you make progress so that we all can learn.