Apache Axis2 Webservice- getting port and ip address of client - apache

I have a Apache Axis2 web service and Im trying to log client ip address and port number. Im able to get the ip address using:
MessageContext inMessageContext = MessageContext.getCurrentMessageContext();
String ip = (String)inMessageContext.getProperty("REMOTE_ADDR");
How can i obtain the port number it came from?

I am newbie for axis2, I cant understand your question. Are you trying to access requester port number or requesting URL port number...?
May be below link useful for you to getting requesting URL port number. Please check
public class MyServlet extends AxisServlet
{
protected MessageContext createMessageContext( HttpServletRequest request, HttpServletResponse response, boolean invocationType ) throws IOException
{
MessageContext mc = super.createMessageContext( request, response, invocationType );
URL url = new URL( request.getRequestURL().toString() );
mc.setProperty( "myPort", url.getPort() );
return mc;
}
}
Of course you must put your class name in axis2/.../web.xml and restart tomcat. Then you can check port number inside any axis2 invocation:
MessageContext mc = MessageContext.getCurrentMessageContext();
int port = ( Integer ) mc.getProperty( "myPort" );
source : How to detect which transportReceiver is used in Axis2

Related

Not getting IP address of Client in Java Spring Web Application

I have a java Spring web application, deployed on an Apache server, in which I wish to capture IP address of client using the following code.
public static String getIpFromRequest(HttpServletRequest request){
String remoteAddr = "";
if (request != null) {
remoteAddr = request.getHeader("X-FORWARDED-FOR");
if (remoteAddr == null || "".equals(remoteAddr)) {
remoteAddr = request.getRemoteAddr();
}
}
return remoteAddr;
}
By this code I'm getting the same IP address for every client. I have referred all stackoverflow questions, but they suggested same above code. Please suggest possible way.

Spring Integration two way communication with gps devices

We are using spring integration application for data receiption from gps devices. For current configuration we are able to receive data from device also respose sent back to device through same connection
current configuration is as
#SpringBootApplication
#IntegrationComponentScan
public class SpringIntegrationApplication extends SpringBootServletInitializer{
private Integer TIMEOUT=1000*60*10;
#Value("${TCP_PORT}")
private Integer TCP_PORT;
public static void main(String[] args) throws IOException {
ConfigurableApplicationContext ctx = SpringApplication.run(SpringIntegrationApplication.class, args);
System.in.read();
ctx.close();
}
#Bean
TcpNetServerConnectionFactory cf(){
TcpNetServerConnectionFactory connectionFactory=new TcpNetServerConnectionFactory(TCP_PORT);
connectionFactory.setSerializer(new CustomSerializerDeserializer());
connectionFactory.setDeserializer(new CustomSerializerDeserializer());
connectionFactory.setSoTimeout(TIMEOUT);
return connectionFactory;
}
#Bean
TcpInboundGateway tcpGate(){
TcpInboundGateway gateway=new TcpInboundGateway();
gateway.setConnectionFactory(cf());
gateway.setRequestChannel(requestChannel());
gateway.setRequestTimeout(TIMEOUT);
return gateway;
}
#Bean
public MessageChannel requestChannel(){
return new DirectChannel();
}
}
and message end point
#MessageEndpoint
public class Echo {
#ServiceActivator(inputChannel="requestChannel")
public byte[] echo(byte[] in,#SuppressWarnings("deprecation") #Header("ip_address") String ip){
//here we receive packet data in bytes from gps device
return "".getBytes();//string will contains expected result for device.
}
Above configuartion works fine for one way communication. but we want to implement two way communication. What we want after connection established between server and device we want to send message explicitely.To send command through server we dont know ip and port of device, so how can we send command through server to connected device.
I am trying following solution
created oubound channel adapter
#Bean
public TcpSendingMessageHandler tcpSendingMessageHandler() {
System.out.println("Creating outbound adapter");
TcpSendingMessageHandler outbound = new TcpSendingMessageHandler();
return outbound;
}
then created gateway for explicite message send, this will be called from service where we want to send data explicitely
#MessagingGateway(defaultRequestChannel="toTcp")
public static interface tcpSendService {
public byte [] send(String string);
}
After calling gate way following service activator invoked where we are setting connection ip and port, these ip and ports will be from connection established while receiving data from device
#ServiceActivator(inputChannel="toTcp", outputChannel="fromTcp")
public String send(String in){
System.out.println(new String(in));
TcpNetClientConnectionFactory factory = new TcpNetClientConnectionFactory(ip_extracted_from_inbound_connection, port_extarcted_from_inbound_connection);
factory.start();
tcpSendingMessageHandler.setConnectionFactory(factory);
return in;
}
// for ip and port extraction i am using following service which is inbound sevice
#ServiceActivator(inputChannel="requestChannel")
public byte[] echo(byte[] in,#Header("ip_address") String ip){
System.out.println(new String(in)+ " ; IP : "+ip);
for (String connectionId : factory.getOpenConnectionIds()) {
if(!lastConection.contains(ip))
lastConection = connectionId;
}
return "hello".getBytes();
}
For service activator i am setting new TcpNetClientConnectionFactory every time service called. Ip and port are extracted from TcpNetServerConnectionFactory. whenever device connects with server i am saving its connection ip and port, using these ip and port for data transmission through server but i am getting connection timeout issue.
Kindly help me out and suggest me a solution over it.
Thank you.
Replace the gateway with a pair of Collaborating Outbound and Inbound Channel Adapters.
In order to send arbitrary messages to a connection, you must set the ip_connectionId header.
The challenge, though, is how to direct the reply to the gateway. You would need to capture the replyChannel header from the request and, when a reply is received for that ip_connectionId, set the replyChannel headers.
This will only work, though, if you have only one request/reply outstanding to each device at a time, unless there is some data in the reply that can be used to correlate it to a request.
Another challenge is race conditions, where the device and the server initiate a request at the same time. You would need to look at data in the inbound message to see if it's a request or reply.

Access remote IP address in resource server proxied through Zuul and Apache

For a security check I need access to the user's remote IP address in my resource service. This resource service is a simple recent Spring Boot app, that registers itself with my Eureka server:
#SpringBootApplication
#EnableEurekaClient
public class ServletInitializer extends SpringBootServletInitializer {
public static void main(final String[] args) {
SpringApplication.run(ServletInitializer.class, args);
}
}
All services registered with my Eureka server are dynamically routed through my Zuul routing proxy server based on Angel.SR3 starter-zuul and starter-eureka:
#SpringBootApplication
#EnableZuulProxy
#EnableEurekaClient
public class RoutingProxyServer {
public static void main(final String[] args) {
SpringApplication.run(RoutingProxyServer.class, args);
}
}
The Zuul routing proxy server also configures an AJP connector for the next step:
#Configuration
#ConditionalOnProperty("ajp.port")
public class TomcatAjpConfig extends TomcatWebSocketContainerCustomizer {
#Value("${ajp.port}")
private int port;
#Override
public void doCustomize(final TomcatEmbeddedServletContainerFactory tomcat) {
super.doCustomize(tomcat);
// Listen for AJP requests
Connector ajp = new Connector("AJP/1.3");
ajp.setPort(port);
tomcat.addAdditionalTomcatConnectors(ajp);
}
}
All requests to the dynamic routing zuul proxy are proxied themselves through Apache to provide HTTPS on the standard 443 port:
# Preserve Host when proxying so jar apps return working URLs in JSON responses
RequestHeader set X-Forwarded-Proto "https"
ProxyPreserveHost On
# Redirect remaining traffic to routing proxy server
ProxyPass / ajp://192.168.x.x:8009/
# Also update Location, Content-Location and URI headers on HTTP redirect responses
ProxyPassReverse / ajp://192.168.x.x:8009/
With all this in place the resource service is made available, but unfortunately the remoteAddress that I get from Spring Security is the address of the Zuul proxy/Apache server, not the remote client IP address.
In the past I had used a org.springframework.security.authentication.AuthenticationDetailsSource that preferred the X-Forwarded-For header value over the normal remoteAddress to get the correct IP address, but I can not work out how to pass the proper remote IP address to my resource service when passing through two proxies (Apache + Zuul).
Can anyone help me access the correct remote IP address behind these two proxies, or suggest an alternative approach to get this to work?
Turns out the X-Forwarded-For header was taken from the original request feeding into Zuul to populate HttpServletRequest#getRemoteAddr(). This would then have to be passed on to the proxied backend services through RequestContext#getZuulRequestHeaders().put("X-Forwarded-For", remoteAddr). The following ZuulFilter accomplishes this, even if it isn't appending it's own value to the X-Forwarded-For filter just yet.
#Component
#Slf4j
public class XForwardedForFilter extends ZuulFilter {
private static final String X_FORWARDED_FOR = "X-Forwarded-For";
#Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
// Rely on HttpServletRequest to retrieve the correct remote address from upstream X-Forwarded-For header
HttpServletRequest request = ctx.getRequest();
String remoteAddr = request.getRemoteAddr();
// Pass remote address downstream by setting X-Forwarded for header again on Zuul request
log.debug("Settings X-Forwarded-For to: {}", remoteAddr);
ctx.getZuulRequestHeaders().put(X_FORWARDED_FOR, remoteAddr);
return null;
}
#Override
public boolean shouldFilter() {
return true;
}
#Override
public String filterType() {
return "pre";
}
#Override
public int filterOrder() {
return 10000;
}
}
One might want to clear the header value in Apache before proxying to Zuul to prevent accepting just any value provided by the user: RequestHeader unset X-Forwarded-For
Normally, you can use servletRequest.getRemoteAddr() to get the client’s IP address that’s accessing your Java web application.
String ipAddress = request.getRemoteAddr();
But, if user is behind a proxy server or access your web server through a load balancer (for example, in cloud hosting), the above code will get the IP address of the proxy server or load balancer server, not the original IP address of a client.
To solve it, you should get the IP address of the request’s HTTP header “X-Forwarded-For (XFF)“.
String ipAddress = request.getHeader("X-FORWARDED-FOR");
if (ipAddress == null) {
ipAddress = request.getRemoteAddr();
}

Getting IP Address of the remote peer in Websocket API for Java EE 7

How can I get the IP address of the remote peer in Websocket API for Java Glassfish ?
Another method, based on this answer to another question, is to get the headers of the HandshakeRequest. The headers you are looking for are either of the following.
origin: [IP Address]
x-forwarded-for: [Possibly a separate IP]
Just for clarity, here's my setup, and how I discovered this:
Wamp 2.5 on MyMachine:6060. This hosts a client HTML page.
Wamp 2.5 on LabMachine:6060 (normal connections) and LabMachine:6443 (secure connections). This acts as a proxy.
GlassFish 4.0 on MyMachine:8080 (normal) and MyMachine:8181 (SSL). This is the endpoint.
I connected to the client page via my own machine, the lab machine, and a colleague's machine. In every case, the origin header of the WebSocket request was
http://MyMachine:6060
However, in each case the x-forwarded-host header was different, matching the IP addresses of the actual client.
See getRemoteAddr()
You will need to cast your socket Session instance to a TyrusSession, which implements the standard JSR-356 Session interface.
You might need to upgrade Tyrus, as I am not sure if the version you have supports this method. I am using Tyrus 1.7 and it works fine for me. Here is how to upgrade.
WebSockets are based on HTTP requests. Therefore you are probably extending an HttpServlet or a WebSocketServlet somewhere, so the usual way of getting the IP from the HttpServletRequest should work:
Example:
public class WebSocketsServlet extends HttpServlet {
private final WebSocketApplication app = new WebSocketApplication();
#Override
public void init(ServletConfig config) throws ServletException {
WebSocketEngine.getEngine().register(
config.getServletContext().getContextPath() + "/context", app);
}
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("IP: " + req.getRemoteAddr());
super.doGet(req, resp);
}
}

Get client IP address for WCF, post operation

I am trying to determine the client's IP address following this link: http://www.danrigsby.com/blog/index.php/2008/05/21/get-the-clients-address-in-wcf/
In .Net 3.0 there was not a reliable way to obtain the address of the
client connecting to a WCF service. In .Net 3.5 a new property was
introduced called RemoteEndpointMessageProperty. This property gives
you the IP address and port that the client connection came into the
service on. Obtaining the this information is pretty straight forward.
Just pull it from the IncomingMessageProperties of the current
OperationContext by the RemoteEndpointMessageProperty.Name and access
the Address and Port properties.
> [ServiceContract] public interface IMyService {
> [OperationContract]
> string GetAddressAsString(); }
>
> public class MyService : IMyService {
> public string GetAddressAsString()
> {
> RemoteEndpointMessageProperty clientEndpoint =
> OperationContext.Current.IncomingMessageProperties[
> RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
>
> return String.Format(
> "{0}:{1}",
> clientEndpoint.Address, clientEndpoint.Port);
> } }
Things to note:
This property only works on http and tcp transports. On all other
transports such as MSMQ and NamedPipes, this property will not be
available.
The address and port are reported by the socket or http.sys
of the service’s machine. So if the client came in over a VPN or some
other proxy that modified the address, that new address will be
represented instead of the client’s local address. This is desirable
and important because this is the address and port that the service
sees the client as, not as the client sees itself as. This also means
that there could be some spoofing going on. A client or something in
between the client and server could spoof an address. So, do not use
the address or port for any security decisions unless you add in some
other custom checking mechanisms.
If you are using duplexing on your
service, then not only will the service have this property populated
for the client, but the client will also have this property populated
for the service for each call from that service.
I have operationContracts of WebInvoke/Post and WebGet. The code works when the client request is a WebGet. But when the client request is a WebInvoke, I will get the WCF host IP. Any solution? Thanks.
Here is the interface
[OperationContract]
[WebGet(UriTemplate = RestTemplate.hello_get)]
Stream hello_get();
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = RestTemplate.hello_post)]
Stream hello_post();
// Code for getting IP
private string getClientIP()
{
//WebOperationContext webContext = WebOperationContext.Current;
OperationContext context = OperationContext.Current;
MessageProperties messageProperties = context.IncomingMessageProperties;
RemoteEndpointMessageProperty endpointProperty =
messageProperties[RemoteEndpointMessageProperty.Name]
as RemoteEndpointMessageProperty;
return endpointProperty.Address;
}
public Stream hello_get()
{
string ip = getClientIP();
...
}
public Stream hello_post()
{
string ip = getClientIP();
...
}
Have you tried using the HttpContext? It's not available in all WCF modes but this could work depending on your environment:
if (HttpContext.Current != null)
{
Trace.WriteLine(
"Who's calling? IP address: '{0}', Name: '{1}', User Agent: '{2}', URL: '{3}'.",
HttpContext.Current.Request.UserHostAddress, HttpContext.Current.Request.UserHostName,
HttpContext.Current.Request.UserAgent, HttpContext.Current.Request.Url);
}