Spring Multipart/Form-data csrf issue - spring

i've been having issues with csrf validation with a multipart/form-data type of form, since it didnt let me authenticate nor upload my files, returning a 403 when trying to execute the call.
After some reseach i've found that supposedly, "multipart/form-data" forms have trouble with csrf, and thus i had to add the
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
annotation to each form in my .xhtml file.
(Also tried the form action='', variation)
And yet it kept returning that my csrf value was null
after some more research, i've tried adding the SpringMultipartFilter
<filter>
<display-name>springMultipartFilter</display-name>
<filter-name>springMultipartFilter</filter-name>
<filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>springMultipartFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
and also stated the filterMultipartResolver bean in the application context of the presentation part:
<bean id="filterMultipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="-1" />
</bean>
and after doing that, Chrome did let me validate my user, and did let me press the upload button, returning a 200 (OK) code
but, the file is not getting uploaded and debugging shows that my methods are not being called, consoles are not returning an error both Java nor Chrome Debug console, so im a little lost any help to solve or to get actual knowledge of what is happening would be appreciated, thanks.
Im using Spring+Primefaces+Maven.
Upload form in .xhtml:
<h:form id="uploadForm" enctype="multipart/form-data">
<input type="hidden" name="${_csrf.parameterName}"
value="${_csrf.token}" />
<p:fieldset id="uploadBlock"
legend="#{message['cmb.title1.text.label']}">
<br />
<h:panelGroup layout="block"
style="float : left; margin-right : 10%;">
<h:panelGrid id="display1">
<p:fileUpload update=":tableForm:comparisonTable #this"
fileUploadListener="#{ComparisonCSVController.upload}"
allowTypes="/(\.|\/)(csv)$/i" mode="advanced" fileLimit="1"
description="Select a csv file">
</p:fileUpload>
</h:panelGrid>
</h:panelGroup>
</p:fieldset>
<br />
</h:form>
Im certain its not a problem with the actual methods of my beans or my beans, since everything was working till i enabled spring security, and if i turn it off, everything runs smooth, but i need it enabled, so im facing this problem.

Fixed after messing with the order of the filters in the web.xml.
The order has to be:
- Primefaces filter- (i did edit out a FORWARD tag)
- MultiPart filter-
- Spring Filter -
- Prettyfaces filter, with ASYNC tag on-
Thank you.

Related

AjaxRenderKitFactory is blocking AJAX in my web project

I am facing an issue related to Ajax in JSF 2.0
We have 2 web projects (WARs) in the same EAR. the first project is having the following in the faces-config.xml
<factory>
<faces-context-factory>
com.ibm.faces.context.AjaxFacesContextFactory
</faces-context-factory>
<render-kit-factory>
com.ibm.faces.renderkit.AjaxRenderKitFactory
</render-kit-factory>
</factory>
For some reason, the com.ibm.faces.renderkit.AjaxRenderKitFactory is blocking ajax in the other web project, if I removed this section, ajax works fine.
I mean by Ajax here, the rendering for
<h:form>
<h:selectOneMenu value="#{myBean.selected}">
<f:selectItem itemValue="#{null}" itemLabel="ABC" />
<f:selectItem itemValue="one" />
<f:selectItem itemValue="two" />
<f:selectItem itemValue="three" />
<f:ajax listener="#{myBean.listener}" render="result" />
</h:selectOneMenu>
<h:outputText id="result" value="#{myBean.selected} #{myBean.result}" />
but the following is working fine
<h:commandButton value="commandButton" action="#{myBean.submit}">
<f:ajax listener="#{myBean.listener}" render="result" />
</h:commandButton>
<h:outputText id="result" value="#{myBean.selected} #{myBean.result}" />
I am not having this com.ibm.faces.renderkit.AjaxRenderKitFactory in my faces-config so why it is affecting Ajax in my project?
The com.ibm.faces.renderkit.AjaxRenderKitFactory is designed to enable ajax support in jurassic JSF 1.x versions which didn't have built-in ajax support.
Since JSF 2.0 (Dec 2009), JSF got built-in ajax support with the new <f:ajax> tag. Therefore, external ajax libraries designed for JSF 1.x such as those from IBM becomes unnecessary and they would possibly even conflict, as you faced.
Just remove it altogether. In JSF 2.x and newer you don't need external libraries to use ajax. Moreover, you should upgrade any JSF 1.x component libraries to a JSF 2.x compatible one.

Spring security logout handling

According to Spring Security 4.0.0 document:
4.2.4 Logout Handling
The logout element adds support for logging out by navigating to a
particular URL. The default logout URL is /logout, but you can set it
to something else using the logout-url attribute. More information on
other available attributes may be found in the namespace appendix.
However, after following security setting in the doc, the URL /logout doesn't show logout page. Instead, it shows
On the contrary, the URL /login works properly.
The following is my setting:
Spring Framework 4.1.6
Spring Security 4.0.0
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Test8</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/security-config.xml</param-value>
</context-param>
</web-app>
security-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<http>
<intercept-url pattern="/**" access="hasRole('USER')" />
<form-login />
<logout />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="aaa" password="111" authorities="ROLE_USER, ROLE_ADMIN" />
<user name="bbb" password="222" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
Spring security automatically enables csrf, which automatically disabled GET logouts.
You can fix this by disabling csrf protection by settings <csrf disabled="true"/> in the <http> , or just using a POST.
See http://docs.spring.io/spring-security/site/docs/4.0.1.RELEASE/reference/htmlsingle/#csrf-logout
Simply, put the following code in the jsp where you want to have the logout-
<c:url var="logoutUrl" value="/j_spring_security_logout" />
<form action="${logoutUrl}" id="logout" method="post">
<input type="hidden" name="${_csrf.parameterName}"
value="${_csrf.token}" />
</form>
Logout
Corresponding entry in the bean configuration file-
<security:logout logout-url="/j_spring_security_logout" logout-success-url="/whateverPageYouWant" invalidate-session="true" />
-This worked for me for spring-security-4.*
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
//...
http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
}
The logout url is "/j_spring_security_logout" so edit your view accordingly
CSRF is by default enabled which will require every POST request (which the logout is) to have a CSRF token. So either disable CSRF (which I will not recommend) or frame the logout inside a form with action as above logout url and a hidden input with CSRF token like this
Note that there is no "logout page". the /logout is Spring's endpoint, that let Spring know that the app asks to logout a user, so it invokes a specific handler.
After logging the user out, Spring redirects to another page, and you can configure the "default target" in your XML.
Add to Spring Security:
<logout
logout-success-url="/anonymous.html"
logout-url="/perform_logout"
delete-cookies="JSESSIONID" />
under http tag
With Spring security 4.2.13 I have a managed to make this work by navigating to the logout URL through a form submission (POST method) instead of using a link.
I replaced <p>Log out</p> with
<form name='f' action='${pageContext.request.contextPath}/logout' method='POST'>
<input name="logout" type="submit" value="Log out" />
<input name="${_csrf.parameterName}" type="hidden"
value="${_csrf.token}" />
</form>
in my view layer, which is a JSP page. This way you will get a button instead of a link.
(In older Spring versions the default logout URL was "/j_spring_security_logout".)

MVC Unobtrusive validating not working properly

I have already configured unobtrusive and jquery-val to validate client-side, when I click on submit button the validate verify the fields and return the propers messages from the model, after that the aplication hint the controller action ignoring the jquery-val and submit the form.
So, the validation works but still submitting.
I have already checked the correctly scripts:
<script src="/Scripts/jquery-2.1.1.js"></script>
<script src="/Scripts/jquery.unobtrusive-ajax.js"></script>
<script src="/Scripts/jquery.validate.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js"></script>
And the configuration on web.config:
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
Also my model there are the proper validation notation and in my view I use
#Html.ValidationSummary(true)
What I'm doing wrong?
thanks!

Login-bar with Spring Secuirty

I'm developing a Spring-based web application by using Spring Boot and Spring Security.
I've a specific and detailed login page {mywebapp}/login, but I'd like to have also a login-bar in every page with the aim to offer a fast login facility.
How can I setup my project to achieve this goal (by using Java Config, hence annotations and methods, avoiding xml files)?
If I got your question well, you have to use whatever templating system you are using to generate the html pages and add a section to your layout that is shared across all pages consisting of a form like this (I'm assuming you are using spring-security defaults):
<form action="${request.contextPath}/login" method="POST">
<input type="text" name="username" value="" placeholder="Username" />
<input type="password" name="password" placeholder="Password" />
<input name="submit" type="submit" value="Login" />
</form>
I'm also assuming you have your login detailed page fully working using spring-security with user/password default login support.
Hope it helps.

Why do I get an invalid-session redirect after a Spring Security logout?

I have a Spring MVC project which uses Spring Security. I am wondering how j_spring_security_logout works. I have a logout link defined in a view like this:
Logout
In my spring-security.xml I have defined this:
<form-login login-page="/login" default-target-url="/wellcome" authentication-failure-url="/loginfailed" />
<logout logout-success-url="/logout" logout-url="/j_spring_security_logout" />
<session-management invalid-session-url="/invalidsession" />
I expected that clicking logout should redirect me to /logout, but instead I get redirected to the invalid-session-url, namely /invalidsession. The logout-success-url is ignored.
However when I delete session-management, logging out does indeed redirect me to /logout.
This is explained in the Spring Security reference manual.
You can't really use the session-expiry facility unless the session cookie is deleted when you log out.
Use just this one and it should work (without logout-url):
<logout logout-success-url="/logout" />
I think you may experience problems by using both logout and session management invalid session url because once you've logged out your session is no longer valid.
Update per your additional question, how about this :
<security:logout logout-success-url="/logout?displayLogout=1" />
<security:session-management invalid-session-url="/logout?displayLogout=0" />
And then in your view :
<c:if test="${param.displayLogout == 0}">
<h2>Your session has timed out.</h2>
</c:if>
Update #2, just tried it locally, when you logout your session is invalid and you get redirected to invalid-session-url location you specified in the session-management configuration.
Really interested in the solution now.

Resources