Spring RESTful API getting client information - java

Iv'e been using this guide:
https://spring.io/guides/gs/rest-service
to create a RESTFul web service, my issue I am having is that I do not know how to get information such as the clients IP address, is this possible with this API?
Thanks,

In your Spring Rest Controller you can add HttpServletRequest to get client info.
Example
#GetMapping("/dummyurl")
public Boolean syncWithServNow(HttpServletRequest httpReq, #RequestParam("username") String username) {
System.out.println(httpReq.getRemoteAddr()); // Line 1
}
In most cases it will work. In case like
url is accessed by web server over a proxy server or has a load balancer this will do.
httpReq.getHeader("X-FORWARDED-FOR");

Related

How do I connect REST services (inside containers) together, in Spring Boot?

I'm supposed to build a system with individual REST services using docker compose. One of them is a web app where a user can login, and one of them is an authentication service, so I need to connect to the rest authentication service using a post request, and get the confirmation.
This is my authentication service:
#RestController
public class AuthenticationController {
private final List<User> users=GetUsers();
#PostMapping ("/verify")
public String greeting(#RequestParam String username, #RequestParam String password) {
for (User u :users)
if (u.getUsername().equals(username)&&u.getPassword().equals(password))
return u.getRole();
return "Invalid Credentials ";
}
}
So, how exactly do I connect from inside the web app code into this service and send a post request?
I know I can send a get using this:
String uri = "http://localhost:8080/verify";
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(uri, String.class);
How would I send a post? And how would it work inside containers? I know I can link them together inside docker compose, but how do I do it on the code level? Do I replace the localhost:8080 with containerName:exposedPort?
As you know, Docker containers are individual Linux virtual machines which means localhost inside a Docker container refers to the container itself, not the host.
Docker compose has a feature called DNS resolutions which basically means you can call other services by their container name or container hash id.
So in your web app, you can call API by containerName:containerPort instead of localhost.
For more information, look at this complete implementation.

How to pass user session to a REST webservice

I am making a REST webservice call to a protected webservice from a java application. The application is also protected so that I need to login to the application for accessing it. Actually when I invoke the webservice call, I am getting the LDAP login URL as the response as below instead of expected result from the webservice.
"https://login-stage.oracle.com:443/oam/server/obrareq.cgi?"
Looks the webservice is expecting the user session to be passed. Is there anyway we can pass the user session in the REST webservice client call? Here is my code below.
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource service = client.resource(REST_URI);
restResponse = getResponse(service);
Please suggest an approach for it.
Since you are calling a REST Service there shouldn't be a session based authentication.
Maybe have a look here. RESTful Authentication
If I understand your question correctly, this is not possible or not RESTful.
A RESTful webservice does not keep any session at all, in fact this is one of the strength of this design pattern.
What you can do is, to add user credentials to the requests. The link provided by questionare is a very good starting point and offers some more options.

How to authenticate users in Java(REST) app?

I have some java server application and some WEB interface(jQuery). For REST services i'm using Jersey implementation. I can easily sent JSON to the server from WEB page and vice versa.
Example of my REST service:
#Path("/users")
public class User {
#POST
#Path("/login")
#Consumes(MediaType.APPLICATION_JSON)
public Response authUser(User user) {
//code
}
}
But there is one problem. How can I auth users?
For example, i have some private resources: when user in not log in, he can't see it resource/web page, but when he logined(enter correct name and password) he can see it resource.
I didn't use sping application. I have googled a lot of time but I didn't find easy examples, then i tried to read Jose's Sandoval book "RESTful Java Web Services", in "Security" section a lot of useful information but there isn't examples.
Could you please help me?
There are different ways to approach this I believe. One way is that when the user authenticates, you send him back a token [which expires after some time] and he then passes back that token in subsequent calls.
Save the token to a file or db. In subsequent requests that come from client , compare token timestamp and value.
Once that token expires he has to re-authenticate.

Jersey-request for authentication

I have a working JavaEE 6 web application on Glassfish, this application already has a JSF frontend and has its authentication mechanism((Using CDI and annotation based security) So there is a login screen, user enters username password, press login button and Java EE authentication process begins.
Now I want to "also" expose some of my service classes as a REST service (I will use Jersey probably), so it can also be reached from a mobile device. But what worries me is the login part.
I will use the exact same existing authentication But now I want my application will get this credentials from a Rest Request but not from the login screen. And then continue using the existing validation methods which already exists(check username password from DB,,etc)
I kinda got lost how can I do this, I think I need to use one of these filters to intercept the request and get the username password but not sure how and which one? Or I dont need anything like this?
You can protect the REST service the same way you protect the REST service, for example:
#Path("/foo")
#RolesAllowed({"admin", "customer"})
public class Foo {
#GET
#Produces("text/plain")
#RolesAllows("admin")
public void adminOnly() {}
public void adminOrCustomer() {}
}
I guess you already have roles and mappings for them so just use the same roles you got, the application server will take care of the rest.

How can I store information in the context of a web service?

I use a web service which is responsible for user logins. If a login is successful, a token should be generated.
#GET
#Produces(MediaType.TEXT_PLAIN)
#Path("/login")
public String login(#QueryParam("userName") String name,
#QueryParam("password") String password) {
//Spring Securtity Check
HttpResponse r =loginResponse(name,password);
String s = r.getFirstHeader("Location").toString();
boolean isError = s.contains("login_error");
if(!isError){
//TODO store Token in the application context
MD5 token = new MD5(name+System.currentTimeMillis());
return "token:"+token.getMD5();
}
return "fail";
}
I would like to store the token in the application context, but I don't know how. The token should exist as long as the server application is running. Does the web service have its own application context? Should I use some kind of HTTP servlet to store the information?
store it in memcached, using it you can apply some expiration policy, and also when you have more than one server, it will be an problem to store it in the local memory, store it in global cache like memcached is more apropariate.
I don't quite understand what you call the application context.
Is it ServletContext? You can get it in Jersey using the #Context annotation: #Context ServletContext. You can get is either as a field in your resource, or as a parameter to your method.
The ServletContext is up, while servlet is up. It may be removed by the servlet container depending on its configuration.
Btw. your design is really really bad and insecure. You use GET for login operation and pass both username and password on the url. This means few things:
GET requests can be cached by intermediaries. Do you want it to happen?
Everybody will see password in url. Even if you use SSL, password will be still in url, seen to everyone.
URL is often logged, both by client, servers and intermediaries. You really, really, really don't want the password to be logged.
I'm voting your question up, since it's a great example of a bad design for login.

Categories