Getting Same OpenApi response for all Apache CXF endpoints with OpenApiFeature - spring

I'm working on integrating OpenApi to my Apache CXF project (github link with README). I've referred this doc for this purpose.
Issues facing:
openapi.json for both the CXF endpoints are returning same json response
from the swagger-ui page when I try to invoke any of the endpoint request is going to invalid paths.
Ex. For carSample endpoint, GET /car:
Expected request URL : http://localhost:9090/api/carSample/car?page=1
Actual request URL : http://localhost:9090/car?page=1
Can anyone let me know where am I going wrong here?

Apparently, my problem was the same and using the following customizer helps:
<bean id="swagger2Feature" class="org.apache.cxf.jaxrs.openapi.OpenApiFeature">
...
<property name="customizer">
<bean class="org.apache.cxf.jaxrs.openapi.OpenApiCustomizer">
<property name="dynamicBasePath" value="true"/>
</bean>
</property>

Related

ADFS integration using Spring SAML -SP metadata vs IDP metadata?

I implemented the Spring SAML sample application using ssocircle and it worked fine. Now I have been trying to implement it for the client's ADFS. Following is the configuration I think that is required, please correct me if I am wrong:
Change the first parameter below, to the federationMetadata.xml url provided by client
<bean class="org.opensaml.saml2.metadata.provider.HTTPMetadataProvider">
<constructor-arg>
<value type="java.lang.String">http://idp.ssocircle.com/idp-meta.xml</value>
</constructor-arg>
<constructor-arg>
<value type="int">5000</value>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
Replace the entity id of SP metadata below:
<bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<property name="entityId" value="replaceWithUniqueIdentifier"/>
<property name="extendedMetadata">
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
<property name="signMetadata" value="false"/>
<property name="idpDiscoveryEnabled" value="true"/>
</bean>
</property>
</bean>
I haven't been able to figure out the following:
All I have received is a url to adfs/../federationMetadata.xml, who is supposed to create the SP metadata?
Am I supposed to create SP metadata and provide to the client, to add it in adfs? Because, that's what I did using sample application. I added the generated metadata to ssocircle
Is my understanding, that point 1 would be adfs url, and point 2 will be SP entity id, correct?
I would be grateful if you could clarify the above to me, also if possible, point me to straightforward tutorial that helps in integrating SAML with Spring security enabled application as I haven't been able to find the same.
Many thanks
To make SAML between SP and IdP (ADFS) work, you have to mutually exchange metadata.
The ADFS metadata are available on the URL https://adfs-host/FederationMetadata/2007-06/FederationMetadata.xml and you can register them in your SP either with HTTPMetadataProvider, or download them and read them from classpath, or file system with ResourceBackedMetadataProvider.
For SP metadata, you have to configure MetadataGenerator (as you have it in your question) and then expose it via FilterChainProxy. Here is a Java configuration (it's equivalent for XML):
#Bean
public FilterChainProxy samlFilter() throws Exception {
List<SecurityFilterChain> chains = new ArrayList<SecurityFilterChain>();
chains.add(new DefaultSecurityFilterChain(
new AntPathRequestMatcher("/saml/metadata/**"), metadataDisplayFilter()));
return new FilterChainProxy(chains);
}
Than, you can access SP metadata on the URL https://sp-host/saml/metadata and register them on ADFS as a Relying Party Trust. Again, you can do this either via URL, or import data from the (downloaded) file.
Basically, you should be fine if you follow Spring Security SAML Reference Documentation which uses XML configuration. In case, you'll need to switch to Java configuration, you can find handy either referenced vdenotaris/spring-boot-security-saml-sample, or my working prototype sw-samuraj/blog-spring-security.

Spring Cloud Config Server without Spring Boot

I have looked at spring-cloud-config client without Spring Boot and many others and have not found a convincing answer. So here it goes again:
Question:
Is it possible, in a Spring app, to use Spring Cloud Config server/client without the automagic configuration of Spring Boot? Is using Spring Boot a requirement for using these frameworks?
If it is:
Is there any documentation that clearly describes what needs to be done in order to enable Spring Cloud Config server/client without Spring Boot?
Is there any sample project that clearly describes what needs to be done in order to enable Spring Cloud Config server/client without Spring Boot??
I'm not aware of documentation or a sample project. However we are doing it in our projects.
You just need to include the configuration server URI as a property source, assuming you are using PropertySourcesPlaceholderConfigurer:
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer" id="propertyPlaceholder">
<property name="locations">
<list>
<value>http://your-config-server.com:8888/application-${spring.profiles.active}.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="false"/>
</bean>
You have to make sure to pass -Dspring.profiles.active=current_profile to the java command line, like you probably would have done with boot.

Issue with Saxon and Xalan in my WebApp when defining a SOAP connector using Spring

I am trying to add a SOAP Web Service to an existing application and am having a large amount of trouble due to Saxon / Xalan conflicts. When my Web Application starts I always get the error:
java.lang.IllegalArgumentException: Unknown type of result: class javax.xml.transform.dom.DOMResult
Stack Trace:
Caused by: java.lang.IllegalArgumentException: Unknown type of result: class javax.xml.transform.dom.DOMResult
at net.sf.saxon.event.SerializerFactory.getReceiver(SerializerFactory.java:154)
at net.sf.saxon.IdentityTransformer.transform(IdentityTransformer.java:24)
at org.springframework.xml.transform.TransformerHelper.transform(TransformerHelper.java:138)
at org.springframework.xml.transform.TransformerObjectSupport.transform(TransformerObjectSupport.java:96)
at org.springframework.ws.wsdl.wsdl11.provider.InliningXsdSchemaTypesProvider.getSchemaElement(InliningXsdSchemaTypesProvider.java:113)
at org.springframework.ws.wsdl.wsdl11.provider.InliningXsdSchemaTypesProvider.addTypes(InliningXsdSchemaTypesProvider.java:101)
at org.springframework.ws.wsdl.wsdl11.ProviderBasedWsdl4jDefinition.afterPropertiesSet(ProviderBasedWsdl4jDefinition.java:233)
at org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition.afterPropertiesSet(DefaultWsdl11Definition.java:182)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1479)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1419)
I prototyped the creation of a SOAP Web Service in a stand-alone Web Application and it worked fine. Checking the prototype, there was no reference to Saxon and transformers were of type:
com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl
Adding the code to my existing (large) Web Application was simple but when transforms occurred the Transform object was of type:
net.sf.saxon.IdentityTransformer
Now Saxon is used by parts of the application and (probably) cannot just be removed. (I have gone done this route and it appears to be a can of worms). I am using a DefaultWsdl11Definition object to create my WSDL schema. How can I state that the transforms for this aspect of the application should use Xalan rather than Saxon? I am using Spring to wire everything up and my servlet class for the SOAP Web Service is:
<bean id="projectSearch" class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
<property name="schema" ref="schema"/>
<property name="portTypeName" value="ProjectSearch"/>
<property name="targetNamespace" value="http://FOO.FOO/foo"/>
<property name="locationUri" value="/soap/reso"/>
<property name="requestSuffix" value="Request"/>
<property name="responseSuffix" value="Response"/>
</bean>
<bean id="schema" class="org.springframework.xml.xsd.SimpleXsdSchema">
<property name="xsd" value="/WEB-INF/ws-project.xsd"/>
</bean>
Does anyone have any advice on how to resolve my Saxon / Xalan woes?
Thanks,
Phil

Moving Spring Application from Glassfish to Tomcat

I've been working on Spring 3.0 web application using Netbeans and Glassfish server. I'm now to the point where I should be deploying the application for public use, however in attempting to move from Glassfish to Tomcat I'm running into an error. My application uses AJAX to grab information from a URL within the application but when I request the url I get the following:
The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers ().
My controller for the information it is requesting looks like so:
#RequestMapping(value = "/electricity/usage/")
public #ResponseBody List<UsageData> getEUsage(HttpSession session) {
UsageDataDAO UsageDAO = new UsageDataDAO();
User u = (User) session.getAttribute("user");
List<UsageData> l = UsageDAO.getAllUsageData(u.getAccountNum(), 'e');
return l;
}
Why is this happening when I migrate to Tomcat?
This error happens because what your browser sends to the server in the "Accept" header does not match what the server can return from the URL /electricity/usage/
If you are using a library like jQuery (and NOT doing cross-domain requests, this is important) then your browser will send this accept header:
Accept: application/json
You getting that error means that the server does not think the URL /electicity/usage can return a JSON response. This is configured in your webmvc-config.xml file. This is what I have in mine related to JSON requests:
<!-- allows rendering responses in XML and JSON formats -->
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver" p:order="1">
<property name="mediaTypes">
<map>
<entry key="xml" value="application/xml"/>
<entry key="json" value="application/json"/>
</map>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<property name="marshaller">
<bean class="org.springframework.oxm.xstream.XStreamMarshaller" p:autodetectAnnotations="true"/>
</property>
</bean>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
</list>
</property>
</bean>
See this tutorial for implementing JSON responses in Spring MVC: http://rwehner.wordpress.com/2010/06/09/2-ways-to-create-json-response-for-ajax-request-in-spring3/
Why this code works on Glassfish, but not Tomcat - that is a good question...
If you are doing a cross-domain request, then this topic applies: JQuery's getJSON() not setting Accept header correctly?

Spring MVC "redirect:" prefix always redirects to http -- how do I make it stay on https?

I solved this myself, but I spent so long discovering such a simple solution, I figured it deserved to be documented here.
I have a typical Spring 3 MVC setup with an InternalResourceViewResolver:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/" />
<property name="suffix" value=".jsp" />
</bean>
I have a pretty simple handler method in my controller, but I've simplified it even more for this example:
#RequestMapping("/groups")
public String selectGroup() {
return "redirect:/";
}
The problem is, if I browse to https://my.domain.com/groups, I end up at http://my.domain.com/ after the redirect. (In actuality my load-balancer redirects all http requests to https, but this just causes multiple browser alerts of the type "You are leaving/entering a secure connection" for folks who have such alerts turned on.)
So the question is: how does one get spring to redirect to https when that's what the original request used?
The short answer is, set the InternalResourceViewResolver's redirectHttp10Compatible property to false:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/" />
<property name="suffix" value=".jsp" />
<property name="redirectHttp10Compatible" value="false" />
</bean>
You could do this on a per-request basis instead, by having your handler method return View instead of String, and creating the RedirectView yourself, and calling setHttp10Compatible(false).
(It turns out the culprit is HttpServletResponse.sendRedirect, which the RedirectView uses for HTTP 1.0 compatible redirects, but not otherwise. I guess this means it's dependent on your servlet container's implementation (?); I observed the problem in both Tomcat and Jetty.)
Spring Boot provides this nice configuration based solution to this if you're running behind a proxy server, simply add these two properties to your application.properties file:
server.tomcat.remote_ip_header=x-forwarded-for
server.tomcat.protocol_header=x-forwarded-proto
This works for me deploying the otherwise unchanged spring-boot-sample-web-ui to Elastic Beanstalk behind an https load balancer. Without these properties the redirect on line 68 of the MessageController defaults to http and hangs.
Hope this helps.
What worked for me is adding this to application.properties server.tomcat.use-relative-redirects=true
So when you have:
public function redirect() {
return "redirect:/"
}
Without the server.tomcat.use-relative-redirects it will add a Location header like: http://my-host.com/.
With the server.tomcat.use-relative-redirects it will look like: /.
So it will be relative to the current page from browser perspective.
Are you sure?
Looking at the code it seems there is no difference. Both variants use the encoded url, see the sendRedirect method in RedirectView:
String encodedURL = isRemoteHost(targetUrl) ? targetUrl : response.encodeRedirectURL(targetUrl);
if (http10Compatible) {
// Other if/else stuff depending on status code
// Send status code 302 by default.
response.sendRedirect(encodedURL);
}
else {
HttpStatus statusCode = getHttp11StatusCode(request, response, targetUrl);
response.setStatus(statusCode.value());
response.setHeader("Location", encodedURL);
}
I had the same problem, but it was triggered by setting up tomcat behind a loadbalancer. The loadbalancer does the SSL handshake and forwards to tomcat a plain http connection.
Solution would be to send a special Http Header in your Loadbalancer, so tomcat can "trust" this connection. Using a servlet filter should set response.isSecure flag. Then overwrite RedirectView to see if response.isSecure and handle it the right way.
I kept this solution short because i am not sure if it machtes the question.
Since Spring Boot 2.1 you have to add the following configuration to your application.properties:
server.use-forward-headers=true
or application.yml:
server:
use-forward-headers: true
if you use springmvc ,you can try the following:
modelAndView.setView(new RedirectView("redirect url path", true, false));
I add scheme="https" in file server.xml for connector with port="80":
<Connector port="80" protocol="HTTP/1.1" URIEncoding="UTF-8"
connectionTimeout="20000" redirectPort="443" scheme="https" />
This started happening for us on Chrome 87 (https://blog.chromium.org/2020/08/protecting-google-chrome-users-from.html), for a quickfix to avoid the warning page in our springboot app we solve it by adding use-relative-redirects: true in the application.yml.
I was also facing same issue...When redirecting it goes to http instead of HTTPS , below changes done :
RedirectView redirect = new RedirectView("/xyz",true);
redirect.setExposeModelAttributes(false);
redirect.setHttp10Compatible(false);
mav = new ModelAndView(redirect);

Resources