This question already has an answer here:
How to invoke a REST service
(1 answer)
Closed 7 years ago.
I have this web service http://qa-takehome-creyzna.dev.aetion.com:4440 that I would like to test. I have the authentication details (username and password) and the service has the following end points: /login, /user/, /user/{id} and /user/search. For all endpoints other than /login an authorization token needs to be passed as an HTTP Header.
The service exposes a login endpoint ( /login) which takes a POST request with two parameters: username and password. Following a successful login, an authentication token will be returned which must be used to make additional requests to the service. For example,if the request is as following,
{
"username": "admin",
"password": "admin"
}
It may return { "token": "1234-0009-999" } and this token will required for making additional request.
I will need to authenticate the web service, create 10 users and then, retrieve that information to validate the users was created correctly. I would like to develop a test plan and implement in Eclipse. How can I get started ?
A web service is basically an extension of the Java Servlet, where the input is processed a bit more and the output is rarely an HTML page.
Netbeans has an excellent tutorial on how to stand up a web service, and if you follow it, you can have a basic web service running within the hour.
https://netbeans.org/features/java-on-server/web-services.html
Don't be fooled by thinking that you must use one IDE (I like netbeans, but others don't) or another. The fancy GUI tools are just writing plain Java classes that might use other plain Java facilities (like JAXB if using XML, etc).
A web service is not much more than a web server that accepts particular kinds of requests, and responds with particular kinds of responses. In Java, web servers are made easier to use by leveraging Servlets. The internal contents of the Servlet will look like
Unpack the request
Validate the request is complete, report an error response if not
Act on the reqeust
Generate a response in the appropriate format
Send the response back as the reply.
--- Edited in response to request ---
Sorry, It seemed too obvious to me. Let me fill in the gaps. Sorry for glossing over the details.
public class MockHttpServletRequest implements HttpServletRequest {
#Override
public String getAuthType() {
throw new UnsupportedOpertationException("unexpected method use");
}
#Override
public String getContextPath() {
throw new UnsupportedOpertationException("unexpected method use");
}
... repeat for all methods ....
}
public class ItemRequestWithBadEncoding extends MockHttpServletRequest {
#Override
public String getMethod() {
return "GET";
}
#Override
public String getHeader(String name) {
if ("content-type".equals(name)) {
return "text/plain-ish"; // this is not a mime-type
}
throw new IllegalArgumentException(String.format("this mock doesn't support %s", name);
}
... fill out the rest of the required request details ...
}
public class CapturingServletResponse implements HttpServletRespose {
private final ArrayList<Cookie> cookies = new ArrayList<Cookie>();
#Override
public void addCookie(Cookie cookie) {
cookies.add(cookie);
}
public List<Cookie> getCookies() {
return Collections.unmodifiableList(cookies);
}
... override other methods and capture them into per-instance fields
with ability to return unmodifiable references or copies to them ...
}
Now back in the testing framework
#Test
public void testItemFetch() {
try {
MockRequest request= ItemRequestWithBadEncoding();
CapturingServletResponse response = new CapturingServletResponse();
Servlet itemRequestServlet = new ItemRequestServlet();
itemRequestServlet.service(request, response);
Assert.assertEquals("unexpected cookies in response", 0, response.getCookies().size());
... other asssertations ....
} catch (Exception e) {
Assert.assertFail(String.format("unexpected exception: %s", e.getMessage());
}
}
Depending on what items you care about, and how much work you need to put into it, you can then flesh out the needed parts of the capture and perhaps parameterize and refine the way you construct your input handling.
Look into spring frameworks.
They go well with other testing frameworks like Mockito and Junits.
Use something like SpringMVCTest or SpringRestAssured, note RestAssured would let you write integration tests.
Read this and this
Related
I am new to Jersey REST Framework , so please excuse if this is a dumb question .
I am using Tomcat with Hibernate and Jersey REST Webservices.
I have got set of HTML pages in my Web APP
login.html
dealer.html
sales.html
I dont want the User to access the HTML pages directly other than login.html
So to resolve this issue , when submit is pressed , under login.html call
following call is made to the backend
#Path("/webchecklogin")
public class WebLoginCheck {
#Context
private HttpServletResponse response;
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces("application/json")
public String getData(LoginInfo loginInfo ) throws JSONException,ClassNotFoundException, SQLException
{
String ID = loginInfo.getID();
String email = loginInfo.getEmail();
// validate this values with Database and if successfully logged in , stored them in session AND cookies also
}
}
And inside dealer.html and sales.html , on page ready i am calling a service as shown below
var checkcallajax = $.ajax({
type: 'GET',
url: url + '/ORIENT/orn/checkifuserloggedin',
jsonpCallback: 'jsonCallback',
success: function(response) {
}
})
#Path("/checkifuserloggedin")
public class CheckIfUserLoggedIn {
#Context
private HttpServletRequest request;
#GET
#Consumes(MediaType.APPLICATION_JSON)
#Produces("application/json")
public String checkIfUserLoggedIn() throws JSONException,ClassNotFoundException, SQLException
{
// On what basis , should i check wheher the USER is logged or NOT
// I tried storing data with Session and cookies , but i am unable to retrive them here
//return true or false
// based on true or false , i am redireting user to appropiate page
}
}
Could anybody please let me know how to approach this
RestFUL web services are supposed to be stateless, so in theory, you could send the credential with every request, and that would be totally stateless from the "server point of view"
Most will find this cumbersome, resource intensive, and storing credentials on the client is somewhat bad from a security point.
The alternative approach could be that your login method returns a token, that needs to be re-sent (in a header maybe) to the server with every request.
The client must know how to store it (session cookie? on the domain
serving html, if you are in a CORS scenario)
The server must know how to validate the token.
On top of it, the validation of the Token can be done in a JaxRS Filter... before reaching your service entry point. And even better, this filter could add roles to the request context, so you can the use the #RolesAllowed annotation with your services.
I "very personnally" avoid relying on the javax.servlet.Session, as this is fundamentally stateful. But, you should be able to do it, given that the clients stores the jSessionId (other other cookie name) in a session cookie. If it does not work, you might have CORS or other domain specific problem, preventing the client from storing and returning this cookie automatically.
Hope it helps.
We want to implement a public RESTful API integrated in our software (written in java) that might be used by various clients to build small e-commerce apps (e.g. for Android or iPhone). This API includes getting a list of products, categories, shopping cart support, etc.
We need to provide an API that will allow user registration and couple of other sensitive functions. How should we protect this API against spam and bruteforcing? In the standard product we use reCAPTCHA. Any alternative for the REST counterpart?
First, think of separation of concerns. What is the purpose of REST API?
A REST API should do offer a service to the client. Client sends a request via REST protocol, and gets a response for its request. In code, this looks something like:
#GET
public Response getClientInfo(#QueryParam("clientId") Integer clientId) {
ClientDTO clientDTO = database.getClientInfo(clientId);
return ResponseWrapper.wrap(clientDTO);
}
Now, you want your REST method doing ONLY this and nothing else. Otherwise, you would put block-bruteforce-and-spam-logic in your REST method and you would get a mess of the code that is not extensible, hard to version, etc. If you want to change your, e.g. blacklisting policy you would have to change each and every REST method, and it's bulky. If you want to check the calls before the make it to REST methods, then take a look at Filters. Every request and response pass through a chain of filters and could be check for misuse of the server.
I don't know what is your technology stack is, but I would suggest looking into these:
JBoss AS7.
DeltaSpike (enables you powerful Interceptors that will check user rights and execution rights before the execution of the REST method).
for example:
#LoggedInUser
#GET
public Response getClientInfo(...) {
...
}
This security annotation #LoggedInUser (which, by the way, you define) will give sign to an Interceptor to check this security constraint, e.g.
#Secures (built in annotation)
#LoggedInUser
public boolean hasRight(Identity identity) {
return identity.isLoggedIn(); //or if he is in certain group of users
}
Context and Dependency Injection context (used in DeltaSpike).
JBoss Filters (a filter chain where you can create your own filter that, for example, checks if some IP is trying to send multiple calls within a very short period ~ 10 lines of code).
An example of the Filter
#Startup
#ApplicationScoped
#Filter(around= "org.jboss.seam.web.ajax4jsfFilter")
public class IPTrackerFilter extends AbstractFilter {
//IPTracker is your #ApplicationScoped bean that remembers all IP addresses accessing the application.
#Inject
private IPTracker fIPTracker;
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
if (!(req instanceof HttpServletRequest)) {
chain.doFilter(req, res);
return;
}
final String ipAddress= ((HttpServletRequest)req).getRemoteAddr();
if (fIPTracker.isBlackListed(ipAddress)) {
//implement error message here
sendErrorMessage(response);
return;
} else {
//all good, continue
chain.doFilter(req, res);
}
}
}
PS. I gave you the link for DeltaSpike, for others is really easy to find. Also, if you find DeltaSpike to obscure, try with JBoss Seam Security Framework.
I setup COMET functionality in my web-app (with the help of such Servlet 3.0 features as AsyncContext and startAsync) to allow for things such as real-time notifications. After adding a filter in front of the sole servlet, I realized that this functionality no longer works because responses are committed automatically after a forward.
Requests that setup COMET functionality require that the responses NOT be committed after the request is handled. This means that I can neither use a forward or redirect to pass processing to my servlet. Thus, i'm stuck using doFilter(), which to my knowledge, does not automatically commit responses after execution.
I was thinking I could wrap requests in a custom HTTPServletRequestWrapper which overrides all the methods dealing with URLs, like so:
public class ActionServletRequestWrapper extends HttpServletRequestWrapper
{
public ActionServletRequestWrapper(HttpServletRequest request)
{
super(request);
}
#Override
public String getRequestURI()
{
String originalRequestURI = super.getRequestURI();
int lastSlashIndex = originalRequestURI.lastIndexOf("/");
return originalRequestURI.substring(0, lastSlashIndex) + "/ActionServlet";
}
#Override
public StringBuffer getRequestURL()
{
String originalRequestURL = super.getRequestURI();
int lastSlashIndex = originalRequestURL.lastIndexOf("/");
return new StringBuffer(originalRequestURL.substring(0, lastSlashIndex) + "/ActionServlet");
}
#Override
public String getServletPath()
{
return "/ActionServlet";
}
}
...but passing this in to doFilter() does not seem to pass execution on to ActionServlet (though through breakpoints I found that the overridden getServletPath() is called at some point). Are there any additional methods I need to overload, or are requests unable to be re-directed in this way?
Considering the fact that no one has answered the question yet, and all my attempts to filter a request in this way have failed, I'm going to go ahead and assume the answer to this question is:
No, you cannot filter a request to a different destination by wrapping it and overloading all of the URL-related methods. The code which determines the destinations of requests apparently does not rely on those methods.
I am migrating some Java EE modules from Spring to EJB and are now facing the problem that I need some sort of pre-authentication prior to calling a service method.
The problem is actually quite easy. A call comes in from an internal protocol handler (some thread started the proprietary protocol handler and received requests using a custom TCP protocol). Not this connection already authenticated the user and wants to call a service method next. This service method requires a principal information (user name) for processing.
So in Spring we simply pushed the SecurityContext to the local thread and removed it when the call was done.
Protocol Handler -> Set SecContext -> Call -> Remove SexContext -> End
Is there anything similar to that in Java EE/JBoss? I know there are "#RunAs" constructs but I don't know if they can be used programmatically. Or is there a way to "log in" using the JAAS LoginContext class? But how do I configure JAAS then?
If this is purely a matter of getting an identity into the JAAS context, you should be able to do something like this:
final String username; // get this from somewhere
Princpal principal = new Principal() {
public String getName() {
return username;
}
};
Subject subject = new Subject(true, Collections.singleton(principal), Collections.emptySet(), Collections.emptySet());
Subject.doAs(subject, new PrivilegedAction<Void>() {
public Void run() {
// do your method call here
}
});
Note that you can return a value from the PrivilegedAction by binding it to a type other than Void, and throw an exception by implementing PrivilegedExceptionAction instead.
Obviously if you have a more sophisticated idea of what a principal is, you could use that (implementing toString, hashCode, and equals would be a good idea).
I like Spring MVC because you can unit test your controllers.
But testing controllers that oauth is another thing. For instance if I want to get the authorization url because I want to Oauth to GData, I would have to deploy the web-app because Google will only accept authorization requests from my domain (the url of my web app), not my development environment whose domain is localhost:8080.
So right now the only way I am testing if my code works is deploying the code and printing out the data that I need to have printed.
My Controller, which is a multi-action controller
public ModelAndView authorize(HttpServletRequest request,
HttpServletResponse response) {
Provider provider = getProvider(request.getAttribute("provider"));
String authUrl = provider.getAuthUrl();
page.put("authUrl", authUrl);
return new ModelAndView("setup","model",page);
}
The provider code, all my dependencies are injected
public String getAuthUrl()
{
oAuthParameters.setScope("http://docs.google.com/feeds/");
try {
oAuthHelper.getUnauthorizedRequestToken(oAuthParameters);
} catch (OAuthException e) {
page.put("authUrl", CANNOT_CONNECT_TO_GOOGLE);
}
String oAuth_Callback="[callback url]";
try {
oAuth_Callback.concat("?oauth_token_secret=").concat(
java.net.URLEncoder.encode
(oAuthParameters.getOAuthTokenSecret(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
page.put("authUrl",INTERNAL_ERROR);
}
oAuthParameters.setOAuthCallback(oAuth_Callback);
String authUrl = oAuthHelper.createUserAuthorizationUrl(oAuthParameters);
return authUrl;
}
It sounds like you have one component (a controller) doing multiple things.
I would break this into
The controller
The OAuth service that communicates with Google
The latter should be injected into your controller, as with just about everything else in Spring.
This allows you, in a unit test, to mock out how your controller behaves when the OAuth component returns different values.
For actually testing integration with Google, you could do two things:
Unit testing of the service that parses the Google OAuth response - mock out the code that does the actual message transport so that you can test how your message parser behaves when google returns a certain type of XML (I'm assuming this is done with XML, but same principle applies regardless of technology) vs another type.
Actual integration tests of the component that sends and receives to google - this might be harder because of the limitations you mentioned.
So, even if they restrict access to certain domains, then you can unit test most of the pieces of the puzzle, and hopefully only have one small segment that has to be "in the wild" to be tested.
Or, could you register a different account for a domain in your test environment? Either way, you should still break up this code into smaller components.