WSO2AM Mediator with conditional properties - wso2-api-manager

We are trying to add an API to WSO2AM which has the problem, that we need to add (invisible for users) an Authorization Key.
We are able to add it using Mediator with that configuration:
<sequence xmlns="http://ws.apache.org/ns/synapse" name="Add_Fahrplan_AuthKey">
<property name="REST_URL_POSTFIX"
expression="fn:concat(get-property('axis2','REST_URL_POSTFIX'),
'&authKey=**HERE_IS_THE_SECRET**')"
scope="axis2"
type="STRING"/>
</sequence>
We have 4 get methods
/location
/departure
/arrival
/journeyDetails <-- needs an different AuthKey
But for the fourth get method journeyDetails we need to add the AuthKey in a different way with different characters.
Is it possible to do that in a Mediator configuration? And in case of yes, how can we do it?
Please keep in mind that we are not very familiar with synapse configuration syntax. We tried
value="/location"
but it resulted in an AM-error while invoking the API and we tried
<filter> with <then> and <else>
which resulted again in an AM error.
Thanks for any help

Related

How to avoid display jssession id in Url using spring 4 java annotation configuration

I found is that jsessionid is injected in the url, how can i avoid displaying jsessionid in url. I am using cookies for to have store login information I have not used any http session. I found below suggestion in xml configuration how would I write using spring java annotation configuration can anyone just let me know
<property name="securityContextRepository" ref="securityContextRepositoryNoJSession"/>
<bean id="securityContextRepositoryNoJSession" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository">
<property name="disableUrlRewriting" value="true"/>
</bean>

How to change spring request mapping to disallow url pattern with suffix

I am using Spring MVC 3.2 and deploying in Apache Tomcat 1.7x. My login url is /web/login but using url /web/login.abc where abc can be any text including space.
In both cases it is returning the same resource which I will like to avoid and return HTTP code 404.
Tried adding the below in web.xml but it did not help
`<beans:bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<beans:property name="useDefaultSuffixPattern" value="false" />
</beans:bean>`
This config depends on the version you're using which you've omitted in your question. Since Spring 4.0.3 the suffix properties are set on the PathMatchConfigurer class. As per Spring doc the config should be under mvc:annotation-driven, e.g.
<mvc:annotation-driven>
<mvc:path-matching suffix-pattern="false" />
</mvc:annotation-driven>
as explained in the docs
Whether to use suffix pattern match (".*") when matching patterns to
requests. If enabled a method mapped to "/users" also matches to
"/users.*". The default value is true.
For Spring 3.2 it should be
<beans:bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<beans:property name="useSuffixPatternMatch" value="false"/>
</beans:bean>`
Also, if you're using the mvc:annotation-driven element in your config, take a note of Biju's answer from this question How do I restrict route extensions in #RequestMapping paths for Spring MVC controllers?

WSO2 API Manager custom handlers

I'm trying to figure out how to customize the default set of API Handlers that is deployed into the Synapse engine for an API's implementation.
The 'API Handlers' section of the architecture overview () shows how deployment of an API results in a Synapse configuration consisting of a standard set of handlers.  The customization instructions indicate that to change this you go to the source view in the management console and alter the xml content. 
That works, but it would mean that to customize the standard set of handlers (for example, to include an additional/custom policy enforcement step), I would need to alter each deployed API by hand in that config.
Is there a place where I can configure API Manager to add additional custom handlers automatically to any API deployed through it, just as it automatically adds handlers like the Authentication Policy, the Throttling Policy, and so on. This way, I can enforce conformance to corporate standards and not require that each API is individually edited, nor force API publishers to use a sequence to add the additional behavior.
From checking the code, it appears that this module may be the one building the synapse config for an API:
.//components/apimgt/org.wso2.carbon.apimgt.impl/1.2.3/src/main/java/org/wso2/carbon/apimgt/impl/APIProviderImpl.java
If I wanted to add the additional logic - is that the appropriate module to override in order to add that behavior, or is there an easier, less intrusive way to do this?
add your handler to dropins
AM_HOME/repository/resources/api_templates/velocity_template.xml and change the following
#if($handlers.size() > 0)
<handlers xmlns="http://ws.apache.org/ns/synapse">
#foreach($handler in $handlers)
<handler xmlns="http://ws.apache.org/ns/synapse" class="$handler.className">
#if($handler.hasProperties())
#set ($map = $handler.getProperties() )
#foreach($property in $map.entrySet())
<property name="$!property.key" value="$!property.value"/>
#end
#end
</handler>
#end
</handlers>
#end
to
<handlers>
**<handler class="com.custom.api.CustomHandler"/>**
<handler class="org.wso2.carbon.apimgt.gateway.handlers.throttling.APIThrottleHandler">
<property name="id" value="A"/>
<property name="policyKey" value="gov:/apimgt/applicationdata/tiers.xml"/>
</handler>
<handler class="org.wso2.carbon.apimgt.usage.publisher.APIMgtUsageHandler"/>
<handler class="org.wso2.carbon.apimgt.usage.publisher.APIMgtGoogleAnalyticsTrackingHandler">
<property name="configKey" value="gov:/apimgt/statistics/ga-config.xml"/>
</handler>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.ext.APIManagerExtensionHandler"/>
</handlers>
this will add your custom handler (<handler class="com.custom.api.CustomHandler"/>)to all the api automatically and other default handlers mentioned above.

Can't create CSRF token with Spring Security

I am using Spring Security 3.2.3 in my Spring MVC application and getting some unexpected behavior.
According to the documentation here, it should be possible to use ${_csrf.token} in the meta tags of my html:
<meta name="_csrf" content="${_csrf.token}" />
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf.headerName}" />
From where I extract the value of "content" using JQuery and place it into the Request Header using AJAX.
For some reason though, Spring Security doesn't "convert" this into an actual token, it just gets sent into the header as a literal string "${_csrf.token}".
Trying the alternate route of using ${_csrf.token} in a hidden input according to the documentation, I then tried to check what the token evaluates to by checking the input's value, but it's still just plain text "${_csrf.token}".
Since it seems that Spring Security isn't in effect, am I missing some kind of configuration? I am currently using a barebones Spring Security Java configuration (as opposed to xml) as shown here:
import org.springframework.context.annotation.*;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.*;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf();
}
}
I know configure is getting called since I put a debug statement in it, so I assume that CSRF protection is indeed enabled since it should be by default.
I realize that the syntax "${}" is JSP Expression Language, and I am currently successfully using it to evaluate the context into an object with Thymeleaf, for example:
th:object="${context}"
So I tried adding "th:" in front of the meta tag's "content" like so:
<meta name="_csrf" th:content="${_csrf.token}"/>
But it results in an exception that this cannot be evaluated:
Exception evaluating SpringEL expression: "_csrf.token"
I think the key here may be figuring out how to get the expression to evaluate properly in my view.
I finally solved this problem, but it basically required rewriting Spring Security. Here it is in all its glory.
First, I followed the suggestions in Eyal Lupu's great blog post here, but I had to tweak it to my situation because of my AJAX requirement.
As for the Thymeleaf situation, the key tidbit is hidden away in the archives of the Thymeleaf forums - Infamous Issue 7.
https://github.com/thymeleaf/thymeleaf-spring/issues/7#issuecomment-27643488
The last comment by the creator of Thymeleaf himself says that:
th:action ... detects when this attribute is being applied on a
tag --which should be the only place, anyway--, and in such case
calls RequestDataValueProcessor.getExtraHiddenFields(... ) and adds the
returned hidden fields just before the closing tag.
That was the key phrase I needed to get the token to work. Unfortunately it's completely not obvious why th:action would also kick off getExtraHiddenFields, but at any rate it does, and that's what matters.
So for anyone struggling with Thymeleaf + Spring Security CSRF + AJAX POST, here are my steps (this is paring it down quite a bit but these are the high-level concepts to solve it):
Implement the Spring interface RequestDataValueProcessor and register it in Spring Security's XML config so you can override the method getExtraHiddenFields, which allows you to insert a hidden input field into the HTML (with the token of course). The token itself is generated with a Java.Util UUID.
With JQuery, read the value from that hidden field and set the Request Header's "X-CSRF-Token" attribute so that it gets sent over HTTP. It's not possible to simply leave the token in the hidden input field because we are not doing a form Submit, instead we use AJAX POST to call methods on the server side.
Extend Spring's HandlerInterceptorAdapter and register it as an interceptor so that every time a POST method is done, the "preHandle" method on the server side is called so it can compare the request token (extracted from the HTTP header in the previous step) to the session's token (should be the same!). After it does this check, it can either allow the request to go through or return an error.
I started with the same source article as you, I think, and the same "you should be able to" add answers as you did. I fought it a different way. I made Thymeleaf give me the answer I wanted.
<meta name="_csrf" th:content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>
Thymeleaf put the attribute "content" with the requested Spring EL contents. I then used the provided JavaScript/JQuery to extract the info from the meta tags straight into the CSRF header.
Before adding the thymeleaf-extras-springsecurity namespace and its dependency into my project, I had similar problems. I never did get the meta tags to work, even with thymeleaf-extras-springsecurity. But I did successfully retrieve Spring Security's csrf token using the hidden input. I have instructions below that work for me:
In the html tag, add:
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"
In your pom.xml (if you're using Maven) you'll need to add the dependency: thymeleaf-extras-springsecurity4.
Then add the hidden input inside your page's body to retrieve the csrf token.
<input type="hidden" id= "csrf-token" th:name="${_csrf.parameterName}" th:content="${_csrf.token}" />
and then use that within your javascript/jquery as follows:
function f1() {
var token1 = $('input#csrf-token').attr("content");
...
$.ajax({
...
type: "POST",
beforeSend: function (request)
{
request.setRequestHeader("X-CSRF-TOKEN", token1);
},
...
This all assumes that you have spring security enabled, and that you have NOT turned off csrf protection.
You have incorrect configuration for springSecurityFilterChain in your web.xml. Correct definition is:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
Spring Security uses set of servlet filters to provide the functionality it is offering (including CSRF protection). These filters are defined as Spring beans (i.e. they are instantiated and managed by Spring application context). DelegatingFilterProxy is a special type of servlet filter, which finds root application context on the registered servlet context and delegates every call to the same named bean.
Your issue is a different one, just stumbled across this one as well and it took me several hours to figure out the cause. The cause for the issue described by you is that you did not enable csrf support within your spring-security.xml
This little snippet needs to go into your security-config.xml:
<!-- Static resources such as CSS and JS files are ignored by Spring Security -->
<security:http pattern="/static/**" security="none" />
<security:http use-expressions="true">
<!-- Enables Spring Security CSRF protection -->
<security:csrf/>
<!-- Configures the form login -->
<security:form-login
login-page="/login"
login-processing-url="/login/authenticate"
authentication-failure-url="/login?error=bad_credentials"
username-parameter="username"
password-parameter="password"/>
<!-- Configures the logout function -->
<security:logout
logout-url="/logout"
logout-success-url="/login"
delete-cookies="JESSIONID"/>
<!-- Anyone can access these urls -->
<security:intercept-url pattern="/auth/**" access="permitAll"/>
<security:intercept-url pattern="/login" access="permitAll"/>
<security:intercept-url pattern="/signin/**" access="permitAll"/>
<security:intercept-url pattern="/signup/**" access="permitAll"/>
<security:intercept-url pattern="/user/register/**" access="permitAll"/>
<!-- The rest of our application is protected. -->
<security:intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
<!-- Adds social authentication filter to the Spring Security filter chain. -->
<security:custom-filter ref="socialAuthenticationFilter" before="PRE_AUTH_FILTER" />
</security:http>
....
...
..
.
Save time by configuring this correctly...
Cheerio,
Flo!
In case you don't need to use Thymeleaf, I'd suggest the following:
Add this to the top of your page:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
Add this to your login form:
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
Add these dependencies to your pom.xml:
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
After struggling a lot, that worked for me.

Spring AsyncServlet with ActiveMQ, Camel and Jetty

I'm trying to use Spring AsyncServlet with Camel and ActiveMQ. I'm using the following versions.
<spring.version>3.2.0.M1</spring.version>
<camel.version>2.10.0</camel.version>
<jetty.version>8.1.3.v20120416</jetty.version>
<activemq.version>5.6.0</activemq.version>
I want to push messages to clients that are connected to the server (Jetty).
My Camel routes looks like the following.
from("mina:udp://source_machine:9998").to("activemq:myqueue");
I've the following in my Spring/Camel configuration based on this.
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost:61616" />
</bean>
<bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory">
<property name="maxConnections" value="8" />
<property name="maximumActive" value="500" />
<property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="pooledConnectionFactory" />
<property name="transacted" value="false" />
<property name="concurrentConsumers" value="10" />
</bean>
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsConfig" />
</bean>
Using the above configuration I'm able to input messages into my queue (at least I don't get any errors.) However, I've no idea how to read from this queue.
Is this the correct way of configuring ActiveMQ when using Spring, Camel and Jetty ?
How do I add/register a MessageListener javax.jms.MessageListener so that I can read from my queue.
How can I control the queue size and make the queue non-persistent?
It it possible to add multiple listeners
Thanks.
Your config looks good for activemq. No idea about jetty. There is no jetty config in the snippet you provided.
In a camel route you can simply use a from activemq endpoint to listen on the queue.
from("activemq:myqueue").to("log:test");
Btw. I typically use the jms ednpoint instead of the ActiveMQ one. This has the advantage that it is easier to switch to another jms provider if you have to at some point.
You can also use the connectionfactory and use you own DefaultMessageListenerContainer in a bean. See the spring configs for how to do this but this has nothing to do with camel then.
You can control the queue size in the activemq config. Using the http://activemq.apache.org/producer-flow-control.html.
You can not make a queue no persistent but you can define the messages you send to be non persistent. http://activemq.apache.org/how-do-i-disable-persistence.html
You can define many listeners and you can even define the number of threads for one listener using the option maxConcurrentConsumers on the from endpoint above.

Resources