I am using #FormParam from jsr311-api-1.0.jar in an old project with Jersey 1.0.3. Is there a way to add a filter which sanitizes and changes all the #FormParams that I am using in the application?
Example code is as follows:
#POST
#Path("myMethod")
public String myMethod(#FormParam("data") String data) {
// Need to change the value of this data to clean XSS
// Code to save data into database
}
Since the JAX-RS 1.0 API (JSR 311) do not provide filters or interceptors, you could consider sanitizing the input in your resource methods.
To do it, you could consider jsoup. Here is an example provided by the documentation:
String unsafe =
"<p><a href='http://example.com/' onclick='stealCookies()'>Link</a></p>";
String safe = Jsoup.clean(unsafe, Whitelist.basic());
OWASP Java HTML Sanitizer can do the trick too. Here is an example provided by the documentation:
PolicyFactory policy = new HtmlPolicyBuilder()
.allowElements("a")
.allowUrlProtocols("https")
.allowAttributes("href").onElements("a")
.requireRelNofollowOnLinks()
.toFactory();
String safeHTML = policy.sanitize(untrustedHTML);
If you are willing to use the Jersey API, it's worth mention that Jersey 1.x provides the ContainerRequestFilter interface that you can implement and modify the state of the request.
Related
Camel's XSLT component has a number of configurable options. According to documentation, these options are added to the URI in the form of
?option=value&option=value&...
However, if the resource is coming over HTTP, all options are used as a query string for the HTTP request and then dropped. From XsltComponent.java:
// if its a http uri, then append additional parameters as they are part of the uri
if (ResourceHelper.isHttpUri(resourceUri)) {
resourceUri = ResourceHelper.appendParameters(resourceUri, parameters);
}
and ResourceHelper.appendParameters():
if (!parameters.isEmpty()) {
String query = URISupport.createQueryString(parameters);
URI u = new URI(uri);
u = URISupport.createURIWithQuery(u, query);
parameters.clear();
return u.toString();
}
The comment in XsltComponent makes me think this is functioning as designed, but it seems like it should be a pretty common scenario. Has anyone found a way around this? I don't want to copy the resources locally, as they are subject to change.
For reference, I'm using the Java DSL inside a Spring Boot application.
No not all options, only any additional options that are not an option on the xslt component, for example if you have ....?foo=bar then because foo is not an option on the xslt component it is used in the http url, as you may need to provide a few options there, to be able to access the resource.
This question already has answers here:
How to implement REST token-based authentication with JAX-RS and Jersey
(2 answers)
Closed 6 years ago.
An application I work on exposes various REST Web Services with the following pattern:
#RequestScoped
#Path("/path")
public class SomeResource {
#GET
public SomeResponse get(
#HeaderParam("authenticationHeader1") String authenticationHeader1,
#HeaderParam("authenticationHeader2") String authenticationHeader2,
#QueryParam("stuff") String stuff,
#QueryParam("moreStuff") String moreStuff)
{
final AuthenticationBean authBean = validateCredentials(authenticationHeader1, authenticationHeader2)
if (!authBean.isValid()) {
return someStronglyWordedResponse(authBean);
}
else {
return someProcessing(authBean, stuff, moreStuff);
}
}
Parsing, validation, and other handling of these authentication headers is done for nearly all resources.
I could make an abstract superclass and simply define validateCredentials() there, as the AuthenticationBean extraction is the same everywhere.
But this strikes me as moderately inelegant in this Java EE7 context, and more important, what if Jimmy forgets to add authentication management when coding a new resource?
Is there a recommended way to parse the HTTP headers of all requests no matter the target resource, and do some generic processing with the results?
Edit:
This app is using Resteasy. Sorry for not mentioning it in the first place. I would prefer to avoid implementation-dependent solutions, but Resteasy mechanisms are also an option.
Jersey provides a ContainerRequestFilter for this. They have a nice tutorial on how to use them here: https://jersey.java.net/documentation/latest/filters-and-interceptors.html
You can just create a global filter and in there do your validation, and if it fails you can abort it with requestContext.abortWith(), as shown in Example 10.2. This example can easily be modified to use your header data instead of a security context. The headers can be accessed using requestContext.getHeaderString() with the header name as the only parameter.
You can also use Name binding (10.5 in the tutorial) to only filter requests for certain resources.
Suppose I need to write a Java client, which calls a REST API (with HTTP GET). I know it returns the data in JSON by default and I do not need to supply any headers.
Now I can use either Apache HttpClient to invoke the API or read the URL directly (get a stream from the URL with url.openStream and read the data). The second approach seems to me much simpler. Which one would you suggest and why ?
All the REST clients provide a wrapper over basic java URL based APIs. These clients are easy to use and provide all the necessary functionality. Your code will be much cleaner in case you use Apache HttpClient. And Apache's API are quite reliable.
I would use special libraries for that, like Jersey client or Apache CXF client.
https://jersey.java.net/documentation/latest/client.html
http://cxf.apache.org/docs/jax-rs.html
These ones are part of Java EE standard, a well defined specification which is widely used.
For JSON, consider https://github.com/FasterXML/jackson. Depending on what client you use, you will find information about how to make it work.
If you are not a big fan of JavaEE, and you look for neat and elegant API, and you are interested in working with a language on top of Java, Groovy HTTPBuilder is such a library that works like a charm!
twitter = new RESTClient( 'https://twitter.com/statuses/' )
resp = twitter.post( path : 'update.xml',
body : [ status:msg, source:'httpbuilder' ],
requestContentType : URLENC )
assert resp.status == 200
assert resp.data.user.screen_name == userName
You can use spring-data-rest and Spring's RestTemplate. No need to write a webapp as you can bootstrap Spring easily into a standalone java application putting AnnotationConfigApplicationContext in the Main(). It's quite simple.
For example, suppose you have a Restful URL, http://localhost:8080/croot/books/ that returns a list of books (deserialized into objects of type Book).
Using Spring's RestTemplate you can do the following:
public Resource<List<Resource<Book>>> findAll() {
return restTemplate
.exchange(
"http://localhost:8080/croot/books/",
HttpMethod.GET,
null,
new ParameterizedTypeReference<Resource<List<Resource<Book>>>>() {
}).getBody();
}
You can also process this using spring-data-hateoas allowing you to further decouple the client from the server and helps process what to do next, say in pagination.
This is a very simplified/contrived example but the REST support in Spring 3 combined with the spring-data framework is quite elegant.
Using Spring you also get the advantage of Jackson for JSON processing as the RestTemplate will have one of the flavors of Jackson's message converters (provided through MappingJackson2HttpMessageConverter for example) in it's list of default converters used for processing.
Best practice for REST resource versioning is putting version information into Accept/Content-Type headers of HTTP request leaving URI intact.
Here is the sample request/response to REST API for retrieving system information:
==>
GET /api/system-info HTTP/1.1
Accept: application/vnd.COMPANY.systeminfo-v1+json
<==
HTTP/1.1 200 OK
Content-Type: application/vnd.COMPANY.systeminfo-v1+json
{
“session-count”: 19
}
Pay attention that version is specified in MIME type.
Here is another request/response for version 2:
==>
GET /api/system-info HTTP/1.1
Accept: application/vnd.COMPANY.systeminfo-v2+json
<==
HTTP/1.1 200 OK
Content-Type: application/vnd.COMPANY.systeminfo-v2+json
{
“uptime”: 234564300,
“session-count”: 19
}
See http://barelyenough.org/blog/tag/rest-versioning/ for more explanation and examples.
Is it possible to implement this approach easily in Java-targeted JAX-RS based implementations, such as Jersey or Apache CXF?
The goal is to have several #Resource classes with the same #Path value, but serving the request based on actual version specified in MIME type?
I've looked into JAX-RS in general and Jersey in particlaur and found no support for that. Jersey doesn't give a chance to register two resources with the same path. Replacement for WebApplicationImpl class needs to implemented to support that.
Can you suggest something?
NOTE: It is required for multiple versions of the same resource needs to be available simultaneously. New versions may introduce incompatibale changes.
JAX-RS dispatches to methods annotated with #Produces via the Accept header. So, if you want JAX-RS to do your dispatching, you'll need to leverage this mechanism. Without any extra work, you would have to create a method (and Provider) for every media type you wish to support.
There's nothing stopping you from having several methods based on media type that all call a common method to do that work, but you'd have to update that and add code every time you added a new media type.
One idea is to add a filter that "normalizes" your Accept header specifically for dispatch. That is, perhaps, taking your:
Accept: application/vnd.COMPANY.systeminfo-v1+json
And converting that to, simply:
Accept: application/vnd.COMPANY.systeminfo+json
At the same time, you extract the version information for later use (perhaps in the request, or some other ad hoc mechanism).
Then, JAX-RS will dispatch to the single method that handles "application/vnd.COMPANY.systeminfo+json".
THAT method then takes the "out of band" versioning information to handle details in processing (such as selecting the proper class to load via OSGi).
Next, you then create a Provider with an appropriate MessageBodyWriter. The provider will be selected by JAX-RS for the application/vnd.COMPANY.systeminfo+json media type. It will be up to your MBW to figure out the actual media type (based again on that version information) and to create the proper output format (again, perhaps dispatching to the correct OSGi loaded class).
I don't know if an MBW can overwrite the Content-Type header or not. If not, then you can delegate the earlier filter to rewrite that part for you on the way out.
It's a little convoluted, but if you want to leverage JAX-RS dispatch, and not create methods for every version of your media type, then this is a possible path to do that.
Edit in response to comment:
Yea, essentially, you want JAX-RS to dispatch to the proper class based on both Path and Accept type. It is unlikely that JAX-RS will do this out of the box, as it's a bit of an edge case. I have not looked at any of the JAX-RS implementations, but you may be able to do what you want by tweaking one of the at the infrastructure level.
Possibly another less invasive option is to use an age old trick from the Apache world, and simply create a filter that rewrites your path based on the Accept header.
So, when the system gets:
GET /resource
Accept: application/vnd.COMPANY.systeminfo-v1+json
You rewrite it to:
GET /resource-v1
Accept: application/vnd.COMPANY.systeminfo-v1+json
Then, in your JAX-RS class:
#Path("resource-v1")
#Produces("application/vnd.COMPANY.systeminfo-v1+json")
public class ResourceV1 {
...
}
So, your clients get the correct view, but your classes get dispatched properly by JAX-RS. The only other issue is that your classes, if they look, will see the modified Path, not the original path (but your filter can stuff that in the request as a reference if you like).
It's not ideal, but it's (mostly) free.
This is an existing filter that might do what you want to do, if not it perhaps can act as an inspiration for you to do it yourself.
With current version of Jersey, I would suggest an implementation with two different API methods and two different return values that are automatically serialised to the applicable MIME type. Once the requests to the different versions of the API are received, common code can be used underneath.
Example:
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
#GET
#Path("/{id}")
#Produces(MediaType.APPLICATION_JSON)
public VersionOneDTO get(#PathParam("id") final String id) {
return new VersionOneDTO( ... );
}
#GET
#Path("/{id}")
#Produces("application/vnd.COMPANY.systeminfo-v2+json;qs=0.9")
public VersionTwoDTO get_v2(#PathParam("id") final String id) {
return new VersionTwoDTO( ... );
}
If method get(...) and get_v2(...) use common logic, I would suggest to put that in a common private method if it's API related (such as session or JWT handling) or else in a common public method of a Service Layer that you access via inheritance or Dependency Injection. By having two different methods with different return types, you ensure that the structure returned is of correct type for the different versions of the API.
Note that some old client may not specify Accept header at all. That means implicitly that they would accept any content type, thus any version of your API. In practice, this is most often not the truth. For this reason you should specify a weight to newer versions of the API using the qs extension of the MIME type as shown in the #Produces annotation in the example above.
If you are testing with restAssured it would look something like this:
import static com.jayway.restassured.RestAssured.get;
import static com.jayway.restassured.RestAssured.given;
#Test
public void testGetEntityV1() {
given()
.header("Accept", MediaType.APPLICATION_JSON)
.when()
.get("/basepath/1")
.then()
.assertThat()
... // Some check that Version 1 was called
;
}
#Test
public void testGetEntityV1OldClientNoAcceptHeader() {
get("/basepath/1")
.then()
.assertThat()
... // Some check that Version 1 was called
;
}
#Test
public void testGetEntityV2() {
given()
.header("Accept", "application/vnd.COMPANY.systeminfo-v2+json")
.when()
.get("/basepath/1")
.then()
.assertThat()
... // Some check that Version 2 was called
;
}
One possible solution is to use one #Path with
Content-Type:
application/vnd.COMPANY.systeminfo-{version}+json
Then, inside the method of the given #Path you can call the version of the WebService
If you're using CXF, you could use the technique specified here to build a new serialization provider (building off the existing infrastructure) which produces the data in the specific format desired. Declare a couple of those, one for each specific format that you want, and use the #Produces annotation to let the machinery handle the rest of the negotiation for you, though it might also be an idea to support the standard JSON content type too so that normal clients can handle it without needing to grok your specialness. The only real question then becomes what is the best way to do the serialization; I presume you can figure that out for yourself…
[EDIT]: Further digging in the CXF documentation leads to the revelation that both the #Consumes and #Produces annotations are considered to be axes for doing selection. If you want to have two methods that handle the production of the response for different media types, you most certainly can. (You'll have to add the serialization and/or deserialization providers if you're using custom types, but you can do the delegation of the majority of the work to the standard providers.) I'd still like to caution that you should still ensure that the resource indicated by the path should be the same in both cases; to do otherwise is not RESTful.
You should be able to use different classes with the same path provided they consume/produce different media types. So this should work with any jax-rs provider:
#Path("/api/system-info")
#Consumes("application/vnd.COMPANY.systeminfo-v1+json")
#Produces("application/vnd.COMPANY.systeminfo-v1+json")
public class SystemInfoResourceV1 {
}
and
#Path("/api/system-info")
#Consumes("application/vnd.COMPANY.systeminfo-v2+json")
#Produces("application/vnd.COMPANY.systeminfo-v2+json")
public class SystemInfoResourceV2 {
}
Goal
Java client for Yahoo's HotJobs Resumé Search REST API.
Background
I'm used to writing web-service clients for SOAP APIs, where wsimport generates proxy stubs and you're off and running. But this is a REST API, which is new to me.
Details
REST API
No WADL
No formal XML schema (XSD or DTD files). There are example XML request/response pairs.
No example code provided
Progress
I looked at question Rest clients for Java?, but the automated solutions there assume you are providing both the server and the client, with JAXB invoked on POJOs to generate a schema and a REST API.
Using Jersey (a JAX-RS implementation), I have been able to make a manual HTTP request:
import com.sun.jersey.api.client.*;
...
ClientConfig clientConfig = new DefaultClientConfig();
Client client = Client.create(clientConfig);
WebResource webResource = client.resource("https://hj.yahooapis.com/v1/HJAuthTokens");
webResource.accept("application/xml");
// body is a hard-coded string, with replacements for the variable bits
String response = webResource.post(String.class, body);
// parse response into a org.w3c.dom.Document
// interface with Document via XPATH, or write my own POJO mappings
The response can look like:
<?xml version="1.0" encoding="utf-8"?>
<Response>
<ResponseCode>0</ResponseCode>
<ResponseMessage>Login successful</ResponseMessage>
<Token>NTlEMTdFNjk3Qjg4NUJBNDA3MkJFOTI3NzJEMTdDNDU7bG9jYWxob3N0LmVnbGJwLmNvcnAueWFob28uY29tO0pVNWpzRGRhN3VhSS4yQVRqRi4wWE5jTWl0RHVVYzQyX3luYWd1TjIxaGx6U0lhTXN3LS07NjY2MzM1OzIzNDY3NTsxMjA5MDE2OTE5OzZCM1RBMVNudHdLbl9VdFFKMFEydWctLQ==</Token>
</Response>
Or, it can look like:
<?xml version="1.0" encoding="utf-8"?>
<yahoo:error xmlns:yahoo="http://www.yahooapis.com/v1/base.rng" xml:lang="en-US">
<yahoo:description>description</yahoo:description>
<yahoo:detail>
<ErrorCode>errorCode</ErrorCode>
</yahoo:detail>
</yahoo:error>
Questions
Is there a way to auto-generate POJOs which can be marshalled/unmarshalled without a formal schema?
Should I attempt to generate those POJOs by hand, with JAXB annotations?
Is there some tool I should be leveraging so I don't have to do all this manually?
It's interesting that they provide an HTTP URL as the namespace URI for the schema, but don't actually save their schema there. That could be an oversight on their part, which an email or discussion-list posting could correct.
One approach is to create your own schema, but this seems like a lot of work for little return. Given how simple the messages are, I wonder if you even need a POJO to wrap them? Why not just have a handler that extracts the data you need using XPath?
Edit: blast from the past, but I saw the comment, reread the question, and realized that the first sentence was hard to understand. So, clarification:
One very good habit, if you're going to write a publicly accessible web service, is to make your schema document available at the same URL that you use for the schema's namespace URI -- or better, have that URL be a link to complete documentation (the W3C XSD namespace is itself a good example: http://www.w3.org/2001/XMLSchema).
I would suggest writing beans by hand, and only annotating with JAXB annotations if you have to. For most accessors/mutators (getters/setters) you do not have to; by default all public bean accessors and fields are considered, name is derived using bean convention, and default is to use elements instead of attributes (so attributes need to be annotated).
Alternatively you can of course write schema by hand, generate beans using JAXB, if you like W3C Schema a lot. And just use resulting code, not schema, for data binding.
As to POJO: that can be very simple. Something like:
#XmlRootElement("Response")
class Response {
public int responseCode;
public String responseMessage;
public String token; // or perhaps byte[] works for automated base64?
}
and similarly for other ones. Or, use getters/setters if you like them and don't mind bit more verbosity. These are just data containers, no need to get too fancy.
And if you must auto-detect type from content, consider using Stax parser to see what the root element, and then bind using JAXB Unmarshaller, handing XMLStreamReader that points to that root element. That way you can pass different object type to bind to.
And finally: sending/receiving requests: plain old HttpURLConnection works ok for GET and POST requests (construct using, say, URL.openConnection()). Jakarta HttpClient has more features if need be. So oftentimes you don't really need a separate REST client -- they may come in handy, but generally build on simple http client pieces.
I find HTTP4E very useful for making REST calls. It is an awesome Eclipse plugin, it has tabs, syntax coloring, auto suggest, code generation, REST HTTP call replay, etc.. It does a great job of HTTP debugging, HTTP tampering, hacking. I am having so much fun with it.
http://www.ywebb.com/
Try JdkRequest from jcabi-http (I'm a developer). This is how it works:
String body = new JdkRequest("http://www.google.com")
.header("User-Agent", "it's me")
.fetch()
.body()
Check this blog post for more details: http://www.yegor256.com/2014/04/11/jcabi-http-intro.html