Dave,

Don't think you can use a wrapper for the upload, as if you do the action
now does not recieve the pararmeters.

Also the cache times out after a period and now get an error page which
looks bad, and could loose what you have typed also.

Another way to do this is to use an interceptor, and if there is a
violation return to the page with an error message.  The page would then
contain the correct salt value.  So next submit it would save correctly
saving the data.

Not sure how exactly the XSRF would fit in here?  Maybe this won't work?

This would also mean the filters are not required, and we could refactor
the LoadSaltFilter into the UIActionInterceptor also.


If this is OK, let me know and I will do the mods.

Cheers Greg.

Here is some code:

/**
 * Cross-site request forgery (XSRF) intercepter which checks POST requests
 * for presence of valid salt value and rejects those without a salt value
or
 * with a salt value not generated by this instance.
 */
public class UIActionSaltInterceptor extends MethodFilterInterceptor {

    private static final long serialVersionUID = 7563014655616490865L;

    private static final Logger LOG = LoggerFactory
            .getLogger(UIActionSaltInterceptor.class);

    @SuppressWarnings("rawtypes")
    private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];

    private String inputResultName = Action.INPUT;

    /**
     * Set the <code>inputResultName</code> (result name to be returned when
     * action fails the salt check). Default to {@link Action#INPUT}
     *
     * @param inputResultName
     *            what result name to use when there is a salt error.
     */
    public void setInputResultName(String inputResultName) {
        this.inputResultName = inputResultName;
    }

    /**
     * Intercept {@link ActionInvocation} and returns a
     * <code>inputResultName</code> when action fails the salt check.
     *
     * @return String result name
     */
    @Override
    protected String doIntercept(ActionInvocation invocation) throws
Exception {
        Object action = invocation.getAction();

        if (action instanceof UIAction) {

            UIAction theAction = (UIAction) action;

            final ActionContext context = invocation.getInvocationContext();
            HttpServletRequest request = (HttpServletRequest) context
                    .get(ServletActionContext.HTTP_REQUEST);

            if (request.getMethod().equals("POST")) {

                String salt = (String) request.getParameter("salt");

                SaltCache saltCache = SaltCache.getInstance();
                if (salt == null || saltCache.get(salt) == null || saltCache
                                .get(salt).equals(false)) {

                    if (LOG.isDebugEnabled())
                        LOG.debug("Failed salt check on action " + theAction
                                + ", returning result name 'input'");

                    String resultName = inputResultName;

                    if (action instanceof ValidationWorkflowAware) {
                        resultName = ((ValidationWorkflowAware) action)
                                .getInputResultName();
                    }

                    theAction.addError("error.permissions.deniedSalt");

                    InputConfig annotation = action
                            .getClass()
                            .getMethod(invocation.getProxy().getMethod(),
                                    EMPTY_CLASS_ARRAY)
                            .getAnnotation(InputConfig.class);
                    if (annotation != null) {
                        if (!annotation.methodName().equals("")) {
                            Method method = action.getClass().getMethod(
                                    annotation.methodName());
                            resultName = (String) method.invoke(action);
                        } else {
                            resultName = annotation.resultName();
                        }
                    }

                    return resultName;
                }
            }
        }

        return invocation.invoke();
    }
}

struts.xml used to further filter the methods as needed:

<interceptor-ref name="UIActionSaltInterceptor" >
          <param name="excludeMethods">*</param>
          <param name="includeMethods">save</param>
</interceptor-ref>




On 12 September 2012 11:13, Greg Huber <[email protected]> wrote:

> Dave,
>
> The multipart/form-data file upload does not pass the request parameters
> in the normal way, so when the ValidateSaltFilter tries to get the "salt"
> parameter it cannot find it.
>
> To resolve this we will need to either exclude this action from the salt
> filter or wrap the http request, extending HttpServletRequestWrapper so
> we can get at the parameter values.
>
> One way this could be done is to access the parameters via
> org.apache.commons.fileupload.servlet.ServletFileUpload and its
> parse(request) method and then strip out the non form field items.
>
> Unless someone else knows of an easier way to get at the parameters?
>
> Cheers Greg.
>

Reply via email to