Question

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!

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top