Spring Webflow - Prevent subflow being accessed directly - spring

I'm using Spring Web Flow in my webapp and i would like to know if there is a general way to prevent some subflows to be accessed directly. These subflows are meant to be accessed just from certain flows, not directly by the url, so in these subflows i would like to check "if i was called from a flow".
is there any mechanisms to achieve it? I was looking at spring security but i couldn't find any useful feature to make this kind of restriction.
Thanks you!

You can check this by using input mapper attribute as shown below. Suppose you have a parent flow which invokes 'subflow-flow'. You need to pass an input value containing the name of the parent flow as:
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
...
<subflow-state id="subflow-flow" subflow="subflow-flow">
<!--flowInitiatedBy should be different for each different parent flow-->
<input name="flowInitiatedBy" value="'parentFlowName'"/>
<transition on="invalidAccess" to="someViewWithMessage"/>
<transition on="processedSubflow" to="someOtherState"/>
</subflow-state>
...
</flow>
Then in subflow you can retrieve the parentflowname and perform the check in yourAction class. You can define subflow as:
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"
start-state="start">
<input name="flowInitiatedBy" type="java.lang.String"/>
<action-state id="start">
<evaluate expression="yourAction.checkAccessibility(flowRequestContext)"/>
<transition on="invalidAccess" to="verifyWhetherDraftsExists"/>
<transition on="continue" to="continueToState"/>
</action-state>
<!--define other states for continue transition -->
...
<end-state id="invalidAccess"/>
<end-state id="processedSubflow"/>
</flow>
In your action class:
public class YourAction{
...
public String checkAccessibility(RequestContext context){
String flowInitiatedBy = context.getFlowScope().get("flowInitiatedBy");
//flowInitiatedBy will be empty if initiated by url.
if(flowInitiatedBy is empty){
return "invalidAccess";
}else{
// dosomething
return "continue";
}
}
...
}
Hope this helps.

I also wish there was some kind of built-in, simple mechanism. However, I just did this a slightly different way I thought I'd share. That is, since my Subflow knows its own name, I just had the first state in the Flow configuration check whether or not the Flow ID (name) matches that hardcoded name:
<decision-state id="subOnly">
<if test="flowExecutionContext.definition.id == 'thisSubflowFlowName'" then="invalidAccess" else="mySubflowFirstState"/>
</decision-state>
Where "invalidAccess" is an end-state like the prior answer shows.

Related

Azure Load test does not report data driven urls

I have a simple load test that basically executes a single webtest on a constant load. That webtest is hooked to an xml file data source that contains urls to my entire site.
When I execute the load test from my local environment, the test summary page reports the individual urls in the "Top 5 slowest pages" i.e. "https://mysite.or/page" . But when I execute the same test from Azure (i.e. changed Test run location to VSTS in .testsettings), the links are reported as "https://{{Enviroment}}{{Sitemap.url.loc}}". This seems to be just a reporting issue and I can validate that azure is correctly invoking the urls from the data source. Why would the tests from Azure not report the url constructed from the datasource?
Load Test Summary: Executed from Local
Same test executed on Azure
Webtest:
<?xml version="1.0" encoding="utf-8"?>
<WebTest Name="GenericSitemap" Id="02954e81-f3a7-4c9c-94f5-3a4304f88361" Owner="" Priority="2147483647" Enabled="True" CssProjectStructure="" CssIteration="" Timeout="0" WorkItemIds="" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010" Description="" CredentialUserName="" CredentialPassword="" PreAuthenticate="True" Proxy="default" StopOnError="False" RecordedResultFile="" ResultsLocale="">
<Items>
<Request Method="GET" Guid="01c37ffa-92db-42e8-9d25-a042dcd0123d" Version="1.1" Url="https://{{Enviroment}}{{Sitemap.url.loc}}" ThinkTime="0" Timeout="300" ParseDependentRequests="True" FollowRedirects="True" RecordResult="True" Cache="False" ResponseTimeGoal="0" Encoding="utf-8" ExpectedHttpStatusCode="0" ExpectedResponseUrl="https://{{Enviroment}}{{Sitemap.url.loc}}" ReportingName="" IgnoreHttpStatusCode="False" />
</Items>
<DataSources>
<DataSource Name="Sitemap" Provider="Microsoft.VisualStudio.TestTools.DataSource.XML" Connection="|DataDirectory|\..\Data\sitemap.xml">
<Tables>
<DataSourceTable Name="url" SelectColumns="SelectOnlyBoundColumns" AccessMethod="Random" />
</Tables>
</DataSource>
</DataSources>
<ContextParameters>
<ContextParameter Name="Enviroment" Value="mysite.net" />
</ContextParameters>
</WebTest>
Thanks to #AdrianHHH. I got it working by creating a requestPlugin and setting it on the data driven requests.
Here's my plugin:
[DisplayName("Set Request Params")]
[Description("Fix request urls when run from Azure")]
public class SetRequestParams : WebTestRequestPlugin
{
public override void PreRequest(object sender, PreRequestEventArgs e)
{
e.Request.ReportingName = e.Request.Url;
}
}

global transition on exception and transition not found

I have 3 spring web-flows - flow1, flow2, flow3. flow2 and flow 3 have assigned parent flow1 like this :
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"
parent="flow1">
In flow1 i have a global-transition and an end-state :
<end-state id="flowInterrupted" view="flowInterruptedPage"/>
<global-transitions>
<transition on-exception="com.core.exceptions.policy.InvalidPolicyContactException" to="flowInterrupted">
<evaluate expression="webFlowService.clearCurrentInterruptCause()"/>
</transition>
</global-transitions>
At some point in my application, in flow2 a subflow flow3 is called
<subflow-state id="stateInFlow2WhereSubFlow3IsDefined" subflow="flow3">
</subflow-state>
, and in flow3, an InvalidPolicyContactException is thrown. It is properly found in flow1 (as its get's to clearCurrentInterruptCause()) but later an exception is thrown, that the flowInterrupted transition is not found in flow2 - and that's true, cause it's in flow1 (where the global-transition is defined). Here is the exception :
org.springframework.webflow.engine.NoMatchingTransitionException: No transition found on occurence of event 'flowInterrupted' in state 'stateInFlow2WhereSubFlow3IsDefined' of flow 'flow2' -- valid transitional criteria are array<TransitionCriteria>[exit, contactSelected] -- likely programmer error, check the set of TransitionCriteria for this state at org.springframework.webflow.engine.TransitionableState.getRequiredTransition(TransitionableState.java:93) at org.springframework.webflow.engine.TransitionableState.handleEvent(TransitionableState.java:119)
at org.springframework.webflow.engine.SubflowState.handleEvent(SubflowState.java:116)
at org.springframework.webflow.engine.Flow.handleEvent(Flow.java:555)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.handleEvent(FlowExecutionImpl.java:388)
at org.springframework.webflow.engine.impl.RequestControlContextImpl.handleEvent(RequestControlContextImpl.java:210)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.endActiveFlowSession(FlowExecutionImpl.java:412)
at org.springframework.webflow.engine.impl.RequestControlContextImpl.endActiveFlowSession(RequestControlContextImpl.java:238)
When I change end-state id="flowInterrupted" to view-state it works fine. when it's called from other flows, that have flow1 as parent it works also fine. When I remove parent=flow1 from flow3, I wouldn't catch an exceptin on global-transition. The only problem is, when an exception is raised from a subflow.
Any help would be appreciated - I can of course put flowInterrupted state in flow2 and solve the problem, but I would like to understand, why this is happening
Thanks.
add
<transition on="flowInterrupted" to="flowInterrupted"/>
in your global transition

How to return Java Set object to webflowc state

I am new to spring web flow , my requirement is return a set object to spring web flow action state by evaluating an expression .I am facing problem with below code please correct me.
<action-state id="openDocument">
<set name="requestScope.startPoint" value="requestParameters.startPoint" />
<set name="requestScope.fileName" value="requestParameters.fileName" />
<set name="requestScope.ext" value="requestParameters.ext" />
<evaluate expression="workflowController.workflowopenFile(requestScope.startPoint,requestScope.fileName,requestScope.ext)"></evaluate>
</action-state>
return the expected object from workflowopenFile() , and set it to a variable in flow with result attribute.
I solved my problem. the problem was in
add return attribute to evaluate tag . (result = "workflowSet").

How to set a literal String flowScope value on-exception?

In my Spring web flow app, one of my action-state transitions looks like this:
<transition on-exception="com.foo.BarException" to="barView">
<set name="flowScope.error" value="foo.bar" type="string" />
</transition>
I would like to set flowScope.error to the literal String "foo.bar", but Spring interprets this as a reference to the foo object's bar attribute. How can I force Spring to take the String literally?
I figured it out: the value needs needs to be enclosed in single quotes:
<set name="flowScope.error" value="'foo.bar'" type="string" />

Returning value (output) from web flow

I am using spring web-flow 2.0 and I need to return a variable from sub-flow to parent flow like:
<end-state id="end" >
<output name="mvViewBean" value="viewBean" />
</end-state>
and use it inside my parent flow like :
<subflow-state id="updateSubflowState" subflow="mv-update" >
<on-exit>
<evaluate expression="mvService.onblabla(mvViewBean)" />
</on-exit>
</subflow-state>
Do i need to define variable definitions or something else?
Just came across this issue...The currentEvent does work, but if you indicate that you accept the variable in your updateSubflowState through a
<output name="mvViewBean" value="flowScope.mvViewBean"/>
then you will be able to access it as mvViewBean.
Yo can get the output values getting attribute in currentEvent.
<subflow-state id="updateSubflowState" subflow="mv-update" >
<on-exit>
<evaluate expression="mvService.onblabla(currentEvent.attributes.mvViewBean)" />
</on-exit>
</subflow-state>

Resources