Prevent XXE (External Entity Processing) Attack with JAXB + Spring RESTful Web Services - spring

I know that we can prevent the XXE attack by setting the property IS_SUPPORTING_EXTERNAL_ENTITIES in the abstract class XMLInputFactory to false in JAXB.
I have also seen this stackoverflow answer.
My question here is,
How do I create a instance of XMLInputFactory and set this IS_SUPPORTING_EXTERNAL_ENTITIES property to false when the spring application loads up. And that particular XMLInputFactory instance should only be used for all the JAXB conversion for all the classes that uses javax.xml.bind.annotation package.

Spring uses RequestMappingHandlerAdapter which is an AbstractHandlerMethodAdapter that supports HandlerMethods with the signature -- method argument and return types, defined in #RequestMapping.
There are 7 seven HttpMessageConverters and one of them is Jaxb2RootElementHttpMessageConverter
Jaxb2RootElementHttpMessageConverter is from the spring-web package.
From 3.2.8 version of spring-web onwards Jaxb2RootElementHttpMessageConverter sets the processExternalEntities to false which in turn sets the XMLInputFactory property IS_SUPPORTING_EXTERNAL_ENTITIES to false.
Refer : Jaxb2RootElementHttpMessageConverter from Spring
Answer use
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.2.8.RELEASE</version>
</dependency>

Related

How to generate OpenApi 3.0 spec from existing Spring Boot App?

I have a project (Spring Boot App + Kotlin) that I would like to have an Open API 3.0 spec for (preferably in YAML). The Springfox libraries are nice but they generate Swagger 2.0 JSON. What is the best way to generate an Open Api 3.0 spec from the annotations in my controllers? Is writing it from scratch the only way?
We have used springdoc-openapi library in our kotlin project, and it meets our need for automating the generation of API documentation using spring boot projects.
It automatically deploys swagger-ui to a spring-boot application
The Swagger UI page should then be available at:
- http://server:port/context-path/swagger-ui.html
The OpenAPI description will be available at the following url for json format:
- http://server:port/context-path/v3/api-docs
Add the library to the list of your project dependencies (No additional configuration is needed)
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.2.32</version>
</dependency>
You could look at spring-restdocs and restdocs-api-spec.
spring-restdocs takes a test-driven approach to API documentation which has many advantages over the introspection-driven approach spring-fox uses. restdocs-api-spec is an extension for spring-restdocs that adds API specification support. Currently it supports OpenAPI2 OpenAPI3 and Postman.
I decided to implement my own generator https://github.com/jrcodeza/spring-openapi maybe you can check it out too. It's based on reflection and supports javax and spring annotations. It also generates inheritance model (with discriminators) based on Jackson annotations. Besides you can define your own interceptors if you want to alter generation process (e.g. when you have your own annotations and need to adjust generated sections of schema). You can use it in runtime mode or as a maven plugin. There is also OpenAPI3 to java client generator, which generates the model from openapi3 spec. Again it generates also Javax annotations and Jackson annotations for correct inheritance.
If you're using jax-rs this tutorial helps. It uses the Apache CXF implementation. I couldn't find any other implementation of jaxrs that uses Spring Boot AND generate Open API 3.0 spec.
You'll need these depedencies:
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-service-description-openapi-v3</artifactId>
<version>3.2.4</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>swagger-ui</artifactId>
<version>3.13.6</version>
</dependency>
Here is the general configuration, more detail is in the link:
#Configuration
#EnableAutoConfiguration
#ComponentScan(basePackageClasses = PeopleRestService.class)
public class AppConfig {
#Autowired private PeopleRestService peopleRestService;
#Bean(destroyMethod = "destroy")
public Server jaxRsServer(Bus bus) {
final JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();
factory.setApplication(new JaxRsApiApplication());
factory.setServiceBean(peopleRestService);
factory.setProvider(new JacksonJsonProvider());
factory.setFeatures(Arrays.asList(new OpenApiFeature()));
factory.setBus(bus);
factory.setAddress("/");
return factory.create();
}
#Bean
public ServletRegistrationBean cxfServlet() {
final ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new CXFServlet(), "/api/*");
servletRegistrationBean.setLoadOnStartup(1);
return servletRegistrationBean;
}
}
https://dzone.com/articles/moving-with-the-times-towards-openapi-v300-adoptio
You can also refer to
https://www.baeldung.com/spring-rest-openapi-documentation
which provides a tutorial on implementing OpenAPI 3.0 with a SpringBoot 1.x or 2.x application using springdoc-openapi.
To summarize, you just add the maven dependency for springdoc-openapi into your application and when you bootRun, go to path
http://server:port/v3/api-docs.yaml/ and you will download an Open API 3.0 spec file in yaml, generated from your application's code.
You can do some other stuff with springdoc-openapi, by accessing the following when your SpringBoot application is running:
http://server:port/v3/api-docs: Gives your spec file in Json format.
http://server:port/swagger-ui.html: Access this in your browser and you will see the swagger documentation.

Cannot construct instance of `reactor.core.publisher.Mono` Spring Cloud OpenFeign and Spring boot 2

Goal: migration from Spring Boot 1.x (webMvc) to version 2 (webFlux) and Spring Cloud Edgware SR2 to FinchleyM8 (awaiting release version).
Problem: Feign -> OpenFeign. OpenFeign under the hood uses RxJava but WebFlux - Reactor3. At the current moment when I using Mono as returned type, I have got an error:
Caused by: org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class reactor.core.publisher.Mono]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of reactor.core.publisher.Mono (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
Code example:
#FeignClient(name = "thirdpartyresource", url = "${third.party.resource.url}")
public interface ThirdPartyResource {
#PostMapping(value = "/validate", consumes = APPLICATION_FORM_URLENCODED_VALUE)
Mono<ValidationResultDto> validate(MultiValueMap multiValueMap); // WORKS BAD
// Single<ValidationResultDto> validate(MultiValueMap multiValueMap); WORKS WELL
}
Question:
Do I need to create my own converter Single to Mono or it's some problems of spring-cloud-starter-openfeign and all should work OOTB?
The reactor.core.publisher.Mono belongs to the spring-boot-starter-webflux jar.
Get the latest version of it from the mvn repository.
Then add it to your pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.5.3</version>
</dependency>
Also do remove spring-boot-starter-web from your pom.xml, just in case if you have it.
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>-->
This fixed the issue!
You can use those methods to adapt:
For Single<T> rxJavaSingle
Mono.from(RxReactiveStreams.toPublisher(rxJavaSingle))
For Completable rxJavaCompletable
Mono.from(RxReactiveStreams.toPublisher(rxJavaCompletable))

How to inject a bean into JAX RS resource?

I am sure this is most probably a silly question but I am not familiar with JAX RS (and Jersey).
We've had a standalone Java application that basically starts a RESTful service. As part of a refactoring, we've moved this application to be just a thread within another application. That other application uses Spring beans that are defined in an application-context.xml. So, I need to inject some of those beans to the resource class (if that's the correct name for it: the one with #Path annotations, etc.). The problem is I don't know what instantiates this particular class. There is a main class of the legacy app that is creating a (jetty) Server instance with ServletContexthandler to which a ServletHolder is added to which a ResourceConfig is set. Something like that.
So, I can inject my stuff from Spring to this main class but can't see how exactly I can pass those objects to the JAX RS resource?
I am sure I miss something pretty simple.
Edit: I have added a better explanation to my problem and a solution I found below.
Jersey has integration with Spring support. For this case, there are really only two things you need to do:
Make sure you have the integration dependency. You'll also need to the commons logging, so it doesn't complain
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring4</artifactId>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
Just add a ContextLoaderListener along with a WebApplicationContext containing your Spring context configuration.
ServletContextHandler context
= new ServletContextHandler(ServletContextHandler.SESSIONS);
AnnotationConfigWebApplicationContext wac
= new AnnotationConfigWebApplicationContext();
wac.register(SpringConfig.class);
context.addEventListener(new ContextLoaderListener(wac));
Here the SpringConfig is just a "Java config" Spring configuration class. If you wanted you could use an XML application context, but the example I used in the below link uses a Java config class, but also show how to easily import an XML into the class if you just want to use your XML config. You can combine two.
That's pretty much it. Once you have this configured, you should be able to #Autowired your Spring beans into your Jersey resources.
For a complete example, check out this GitHub repo
Maybe I wasn't able to explain well my problem, so basically it was a problem of how to inject beans into JAX-RS resource classes when the actual JAX-RS app is not being instantiated through its own DI-mechanism but from somewhere else. In my case I already had a Spring container that creates those beans and there was no easy way to link the Spring's own bean application context to the JAX-RS's one. A better solution would have been the one already answered but additional problem is that our existing Spring solution is XML-based, whereas the #Injected annotation in JAX-RS won't work with it (at least that's what I've read in their documentation).
So, JAX-RS supports #Injected annotations and in order for it to know where to get bean definitions from, I had to go to the class that defines the ResourceConfig and add the following lines to it:
.register(new AbstractBinder() {
#Override
protected void configure() {
bind(beanImpl1).to(BeanInterface1.class);
bind(beanImpl2).to(BeanInterface2.class);
}
})
The actual beanImpl1 and beanImpl2 bean instances were coming through the constructor of that class, which in turn was instantiated from our Spring through the XML configuration.

Why doesn't Spring 3.1 automatically use Jackson when POST header Content-Type=application/json?

No configuration or annotation is needed when setting request header "Accept=application/json"
It's almost automatic. Referring to
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-config-enable
Jackson is automatically selected and registered when it is in the classpath (i.e. pom.xml) and you use mvc:annotation-driven in your context config.
It does work automatically - in my controller I used an incorrect annotation - I used #RequestParam - it must be #RequestBody
In my situation, I fixed it with using another source for Jackson, because #RequestBody does not converted to the type I expect.
Instead of Codehause Jackson, I use now fasterxml:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.3.3</version>
</dependency>

Spring MVC: Adding JAXB to the classpath so that it automatically serializes XML

According to Spring MVC documentation, <mvc:annotation-driven/> configures support for JSON if Jackson is in the classpath, and support for XML if JAXB is present in the classpath. Simply by adding a Jackson dependency to my pom.xml, I get JSON support to work! (see: Ajax Simplification in Spring 3.0)
However, after trying to access the same service with accept header "application/xml", I get a 406 Not Acceptable response. What's the simplest way to get JAXB in the classpath? What is necessary to enable support for XML MarshallingHttpMessageConverter?
Update
Taking a look at AnnotationDrivenBeanDefinitionParser, I can see what defines if "jaxb2Present". I set a breakpoint around line 179 to see if the Jaxb2RootElementHttpMessageConverter is indeed being registered like the MappingJacksonHttpMessageConverter is. It isn't...
What's the simplest way to add JAXB to the classpath to make it automatically serialize my XML requests?
It should work. Make sure that the object being returned has #XmlRootElement annotation as required by JAXB.
If you're using Java 6, JAXB is already on the classpath. If you're using Java 5, you'll need to add a reference implementation yourself.
If you're using Maven, you can add to your pom.xml:
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2</version>
</dependency>

Resources