How to get Client IP address in Spring bean - java

I have define a Spring bean.
<beans>
<bean id="remoteService" class="edu.wustl.catissuecore.CaTissueApplictionServicImpl" />
</beans>
Is there any way to get the IP address of client in this class? Similarly as available in the servlet request.getRemoteAddr();

The simplest (and ugliest) approach is to use RequestContextHolder:
String remoteAddress = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes())
.getRequest().getRemoteAddr();
Without knowing more about your bean and how it's wired up, that's the best I can suggest. If your bean is a controller (either subclassing AbstractController or being annotated with #Controller) then it should be able to get direct access to the request object.

The best way to get client ip is to loop through the headers
private static final String[] IP_HEADER_CANDIDATES = {
"X-Forwarded-For",
"Proxy-Client-IP",
"WL-Proxy-Client-IP",
"HTTP_X_FORWARDED_FOR",
"HTTP_X_FORWARDED",
"HTTP_X_CLUSTER_CLIENT_IP",
"HTTP_CLIENT_IP",
"HTTP_FORWARDED_FOR",
"HTTP_FORWARDED",
"HTTP_VIA",
"REMOTE_ADDR" };
public static String getClientIpAddress(HttpServletRequest request) {
for (String header : IP_HEADER_CANDIDATES) {
String ip = request.getHeader(header);
if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
return ip;
}
}
return request.getRemoteAddr();
}

Construct this:
#Autowired(required = true)
private HttpServletRequest request;
and use like this:
request.getRemoteAddr()

Related

Right way to get user's IP

I have the following code which is supposed to get user's IP:
public String getUserIP()
{
Object details = getDetails();
if (details instanceof WebAuthenticationDetails)
{
return ((WebAuthenticationDetails)details).getRemoteAddress();
}
return "";
}
#Nullable
public Object getDetails()
{
Authentication authentication = getCurrentUserAuth();
return authentication != null ? authentication.getDetails() : null;
}
However, under some unknown circumstances it returns 127.0.0.1 instead of real IP.
I decided to re-write like that:
public String getUserIP()
{
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpServletRequest request = attr.getRequest();
String ip = request.getHeader("X-Forwarded-For").split(',')[0];
return ip;
}
But in some cases the header X-Forwarded-For is null. The exception only occurs where getUserIP() from the first snippet returns valid IP address. What's the problem? The web server is tomcat. Thanks in advance.
You can update like this.
public String getUserIP()
{
ServletRequestAttributes attr = (ServletRequestAttributes)
RequestContextHolder.currentRequestAttributes();
HttpServletRequest request = attr.getRequest();
return request.getRemoteAddr();
}
You Can Try this
public static String getUserIP(HttpServletRequest request) {
String xForwardedForHeader = request.getHeader("X-Forwarded-For");
if (xForwardedForHeader == null) {
return request.getRemoteAddr();
} else {
// As of https://en.wikipedia.org/wiki/X-Forwarded-For
// The general format of the field is: X-Forwarded-For: client, proxy1, proxy2 ...
// we only want the client
return new StringTokenizer(xForwardedForHeader, ",").nextToken().trim();
}
}

How to get the sender IP Address in spring integration?

I use Spring integration for Web service message handling. Unfortunately the Message does not contains the sender IP Address. How can I get this information?
#Bean
public SimpleWebServiceInboundGateway myInboundGateway() {
SimpleWebServiceInboundGateway simpleWebServiceInboundGateway = new SimpleWebServiceInboundGateway();
simpleWebServiceInboundGateway.setRequestChannelName("testChannel");
simpleWebServiceInboundGateway.setReplyChannelName("testResponseChannel");
return simpleWebServiceInboundGateway;
}
#ServiceActivator(inputChannel = "testChannel", outputChannel = "testResponseChannel")
public Message getHeaders(Message message) {
// how can I reach the sender IP address here
return message;
}
The SimpleWebServiceInboundGateway doesn't map transport headers by default.
See DefaultSoapHeaderMapper.
Of course you can implement your own, but that really might be enough for you to use:
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest()
.getRemoteAddr();
in that your target #ServiceActivator.
Of course that will work if you don't shift message to a different thread before the service activator. The RequestContextHolder.currentRequestAttributes() is tied with ThreadLocal.
You can retrieve it from HttpServletRequest, using getRemoteAddr() to get access to user IP address and getHeader() to get header value. This is assuming you can modify your controller class.
Perhaps this will help:
#Controller
public class MyController {
#RequestMapping(value="/do-something")
public void doSomething(HttpServletRequest request) {
final String userIpAddress = request.getRemoteAddr();
final String userAgent = request.getHeader("user-agent");
System.out.println (userIpAddress);
}
}

Why is the HttpServletRequest null in the MessageContext?

I am trying to get the IP Address of the client of my JAX-WS SOAP Web Service (an alternative solution is appreciated).
I am using the following code, which works on another project, however this project (integrating with Spring 3.2.4) is returning a null HttpServletRequest when I fetch it from the javax.xml.ws.WebServiceContext (the WebServiceContext is not null):
#Resource
WebServiceContext wsContext;
private String getRemoteIpAddress()
{
MessageContext context = this.wsContext.getMessageContext();
HttpServletRequest httpRequest = (HttpServletRequest) context.get(MessageContext.SERVLET_REQUEST);
String remoteIpAddress = httpRequest.getRemoteAddr();
For further clarity, this is this Web Service class looks like:
#WebService(name = "PService", targetNamespace = "http://server.ps/")
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.WRAPPED)
public class PSystemServiceEndpoint extends SpringBeanAutowiringSupport
Important to note, the application is running as a standalone Java application and includes a Jetty Embeeded Server.
I also use Spring WS and when I need to get IP from remote client I use this function
private String getIpRequest(){
String result = "none";
TransportContext context = TransportContextHolder.getTransportContext();
if(context != null){
HttpServletConnection connection = (HttpServletConnection)context.getConnection();
if(connection != null){
HttpServletRequest request = connection.getHttpServletRequest();
if(request != null){
result = request.getRemoteAddr();
}
}
}
return result;
}
As you can see I don't use WebServiceContext, instead I use WebServiceTemplate so I am not sure if this code is right for you, but I hope it helps.

How to make JAX-WS webservice respond with specific http code

Just like the title says.
#WebService(
targetNamespace = "http://com.lalaland.TestWs",
portName = "TestWs",
serviceName = "TestWs")
public class TestWs implements TestWsInterface {
#EJB(name="validator")
private ValidatorLocal validator;
#WebMethod(operationName = "getStuff")
public List<StuffItem> getStuff(#WebParam(name = "aaa")String aaa,
#WebParam(name = "bbb")int bbb ) {
if ( ! validator.check1(...) )
return HTTP code 403 <------------ Here
if ( ! validator.check2(...) )
return HTTP code 404 <------------ Here
if ( ! validator.check3(...) )
return HTTP code 499 <------------ Here
return good list of Stuff Items
}
Is there anyway I can make a method return a specific HTTP code on demand? I know that some of the stuff, like authentication, internal server errors , etc make the the WS method return 500 and auth errors , but I would like to be able to send these in accordance with by business logic.
Anyone done this before? Been using jax-WS for some time and this was the first time I had this need, tried searching for it and couldn't find an answer anywhere.
Thanks
Only get the current instance of javax.servlet.http.HttpServletResponse and sends the error.
#WebService
public class Test {
private static final Logger LOG = Logger.getLogger(Test.class.getName());
#Resource
private WebServiceContext context;
#WebMethod(operationName = "testCode")
public String testCode(#WebParam(name = "code") int code) {
if (code < 200 || code > 299) {
try {
MessageContext ctx = context.getMessageContext();
HttpServletResponse response = (HttpServletResponse)
ctx.get(MessageContext.SERVLET_RESPONSE);
response.sendError(code, code + " You want it!");
} catch (IOException e) {
LOG.severe("Never happens, or yes?");
}
}
return code + " Everything is fine!";
}
}
See also List of HTTP status codes - Wikipedia, the free encyclopedia
Try this:
Create a SoapHandler like this: http://www.mkyong.com/webservices/jax-ws/jax-ws-soap-handler-in-server-side/ implementing the interface: Handler.handleResponse();
then, inside the handler you are avalaible to modify as you like the http headers, so you can add something like: http://download.java.net/jdk7/archive/b123/docs/api/javax/xml/ws/handler/MessageContext.html
Where you can use the: HTTP_RESPONSE_CODE as you want.
Other resource: http://docs.oracle.com/cd/E14571_01/web.1111/e13735/handlers.htm
Tip: think on soaphandlers as interceptors for soap messages

CXF RESTful Client - How to do basic http authentication without Spring?

I am familiar with using Jersey to create RESTful webservice servers and clients, but due to class loading issues, I am trying to convert a Jersey client into CXF. I believe I want to use an HTTP-centric client but we don't use Spring. We need to use basic HTTP authentication. The user guide has this example:
WebClient client = WebClient.create("http:books", "username", "password", "classpath:/config/https.xml");
The first parameter isn't a URI string. Is it a format used by Spring? Can this method only be used to create WebClients using Spring?
The other way of doing authentication shown is to add a header string:
String authorizationHeader = "Basic " + org.apache.cxf.common.util.Base64Utility.encode("user:password".getBytes());
webClient.header("Authorization", authorizationHeader);
I am guessing that "user:password" should be substituted with the real values, but would appreciate confirmation.
This answer came from the CXF users mailing list.
The first example referenced above had a typo in it. It has been updated to:
WebClient client = WebClient.create("http://books", "username", "password", "classpath:/config/https.xml");
The fourth argument can be null if a Spring config file is (and therefore Spring) is not being used.
So, this worked for me:
private WebClient webClient;
public RESTfulClient(String url, String username, String password)
throws IllegalArgumentException
{
this.username = username;
this.password = password;
this.serviceURL = url;
if (username == null || password == null || serviceURL == null)
{
String msg = "username, password and serviceURL MUST be defined.";
log.error(msg);
throw new IllegalArgumentException(msg);
}
webClient = WebClient.create(this.serviceURL,
this.username,
this.password,
null); // Spring config file - we don't use this
}

Categories