We have a web application built upon Spring Framework 3.2.x (3.2.12-RELEASE at moment) and Spring Security 3.2.x (i.e 3.2.5-RELEASE)
Security is implemented with classical Spring approach. In web.xml we load ApplicationContext and springSecurityFilterChain
<?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">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:META-INF/spring/applicationContext*.xml
</param-value>
</context-param>
...
<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>
As of a change in requirements, we are trying to investigate on how to permit different HttpSessions per tab (or window) within the same browser: in this scenario the same physical user can log in the application using two separate app-users.
I can understand that this is not possibile using JSESSIONID cookie approach. I'm trying using Spring Session (Spring Session and Spring Security
and Spring Session Multiple Session) but i can't manage doing it, having difficulties mixing my XML configuration with the JavaConfig approach shown in links before, Tomcat does not even start with a lot of errors.
I'm new with mixing XML and JavaConfig approch, so..can anyone give me an hint in how to proceed with Spring Session?
Are there other ways to fulfill my requirement?
Spring Session project actually contains a few sample projects that demonstrate usage with Spring XML config. Look for the samples with -xml suffix in the sample name.
Generally speaking, what you need to do is manually register appropriate #Configuration class as a #Bean. For example, if you want to use Spring Session backed by Redis, register RedisHttpSessionConfiguration. You'll find the correct #Configuration class to use by looking at appropriate #Enable*HttpSession annotation (in this case #EnableRedisHttpSession) and determining which class is imported via #Import annotation.
Related
I'm reconfiguring a webapp. I want to move everything out of dispatcher servlet into ContextLoaderListener. (This is due to changes in security configuration beyond the scope of this question)
Question 1, if I have multiple application context xml files, does it matter what order they are loaded? For example does the xml file containing context:component-scan need to be loaded before the xml file specifying DAO and service beans?
Question 2, (or is this moot?) how would I specify the order in which *_applicationContext.xml are loaded assuming that A_applicationContext.xml should be loaded before B_applicationContext.xml which should be loaded before C_applicationContext.xml
My web.xml is as follows:
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>AssessmentDelivery</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AssessmentDelivery</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/*_applicationContext.xml</param-value>
</context-param>
<!-- security filter -->
<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>
</web-app>
Some suggestions:
For these days consider do the configuration for Spring through Javaconfig.
To answer questions 1 and 2 is very important you understand the following:
When you run the app Spring creates an Application Context where exists all the beans created and managed by Spring. Now consider that for that Application Context it should be created from two 'sub' applications contexts, normally they are 'mentioned' in the documentation how ServletApplicationContext and RootApplicationContext
The former should scan all about the Web, such as your #Controllers and #Bean's about infrastructure such as for ViewResolver etc..
The later should scan all about the Server, such as #Service and #Repositories and #Bean's about infrastructure such as for a DataSource etc.
Is very important understand the following:
ServletApplicationContext --> RootApplicationContext
It means the former can get access the latter (it about use dependencies i.e: a #Controller needs a #Service). Therefore it reflects that the Web side can access the server side.
Once said this the following is not possible
RootApplicationContext --> ServletApplicationContext
has no sense that a Bean from the server side want access the web side (a bad practice)
Long time ago I don't use web.xml but
DispatcherServlet + contextConfigLocation (through <init-param>) represents the ServletApplicationContext
ContextLoaderListener + contextConfigLocation (through <context-param>) represents the RootApplicationContext
It does not matter if the beans are declared through:
XML
JavaConfig
annotations #Controller etc.
Spring manages the cycle about in what order the beans are created. So do not matter how the .xml files (in your case) are declared (about the order).
I've got the a WEB-INF/web.xml file with a couple of servlets, along with a context
listener which I use to bootstrap the application. I'd like to use Spring in this
web application. What's the best way to work Spring into this so I can use Spring's
injection mechanisms throughout the entire application - even in the servlets which
exists today?
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Company's XMLRPC service</display-name>
<!-- Servlet Listeners -->
<listener>
<listener-class>com.company.download.context.DefaultServletContextListener</listener-class>
</listener>
<!-- Servlet Declarations -->
<servlet>
<servlet-name>DefaultTrackDownloadServlet</servlet-name>
<servlet-class>com.company.download.web.impl.DefaultTrackDownloadServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>DefaultXmlRpcServlet</servlet-name>
<servlet-class>com.company.download.web.impl.DefaultXmlRpcServlet</servlet-class>
</servlet>
<!-- Servlet Configurations -->
<servlet-mapping>
<servlet-name>DefaultTrackDownloadServlet</servlet-name>
<url-pattern>/track</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>DefaultXmlRpcServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>
Can Spring “live” alongside other servlets in the same webapp?
Yes, Spring MVC is basically just a DispatcherServlet that can make use of a ContextLoaderListener.
These two classes are already setup to interact with one or more ApplicationContext instances and have Spring manage the declared beans.
Your custom Servlet classes are not. If you need to inject a bean into your own Servlet instances, you need to get a reference to the ApplicationContext from the ContextLoaderListener and get the beans you want. There are a few options, whether you do it yourself or use built-in features.
The ContextLoaderListener stores the ApplicationContext it loads into a ServletContext attribute named
org.springframework.web.context.WebApplicationContext.ROOT
So you can retrieve it with that (there's a constant for easy use)
ApplicationContext ac = (ApplicationContext) config.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
Other options exist, see some of them here:
Autowiring in servlet
I want to inject an object in servlet using Spring
I have created a Spring MVC project through eclipse. I believe I used some plugins to generate the project directory. I find here there configuration files.
web.xml
root-context.xml
servlet-context.xml
I am kinda of familiar with Spring MVC & its dependency injection. However I have problems understanding the last two configuration files (root-context & servlet-context).
What kind of configurations do they contain?
Also in may online examples I see mvc-dispatcher-servlet.xml. Why did eclipse not generate this xml file in my project?
[IMPORTANT] I wanted to set up strong security and user authentication for my web app. I have been following online tutorials again and they all create a seperate
xml file named spring-security.xml and add the namespace information to that file. Does it suffice if I just create this file and add the name space information? I mean
dont' I need to import this file to a main file that is scanned by Spring framework?
How do I define and where do I put spring application context.xml file and start wiring the dependencies together? Also if I define everything (all dependencies here) how is this file picked up by the framework?
Thanks,
Configuration Files
If you check your web.xml you will find both of root-context.xml and servlet-context.xml files being referred here. One used by Dispatcher Servlet and other by Context Loader Listenter. You can name your files to whatever unless they are being refereed in web.xml
Eclipse Not generating files
Every editor works its own way. some may generate full fledged project/app with both DispatcherServlet and ContextLoaderListner configured or some with only DispatcherServlet ( with minimal configutaion). Check Spring Roo it starts with basic and gives you the flexibility to generate a strong app.
mvc-dispatcher-servlet.xml is not there
Some of the thing in spring projects are convention based, for example if you are not providing any file to your DispatcherServlet in web.xml spring looks for mvc-dispatcher-servlet.xml file, and if you have provided it won't look for.
Spring Security
To Configure Spring Security you need to provide at least some configuration. But the question is where. You need to add this configuration to your web.xml only. and Hence no need to import this to any other file.
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener- class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/spring-security.xml
</param-value>
</context-param>
<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>
Where to define application context.xml
Just define it any where, configure beans in it.
You can add this file as follows:
a) Either Import this into some other configuration file like root-context.xml or servlet-context.xml
as <import resource="application-context.xml"/>
b) Add this into web.xml with ContextLoaderListner as context param
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:META-INF/spring/application-context*.xml
classpath*:META-INF/spring/abc*.xml
</param-value>
</context-param>
We have been using Spring Security with our application for a few years now. Last week we upgraded Spring Security from version 3.1.4 to 3.2.0. The upgrade went fine and we did not find any errors post the upgrade.
While looking through the Spring Security 3.2.0 documentation we came across the newly added features around CSRF protection and security headers. We followed the instructions in the Spring Security 3.2.0 documentation to enable CSRF protection for our protected resources. It works fine for regular forms but does not work for multipart forms in our application. On form submission, CsrfFilter throws an Access Denied error citing the absence of a CSRF token in the request (determined through DEBUG logs). We have tried using the first option suggested in the Spring Security documentation for making CSRF protection work with multipart forms. We do not want to use the second suggested option as it leaks CSRF tokens through the URLs and poses a security risk.
The relevant part of our configuration based on the documentation is available as a Gist on Github. We are using Spring version 4.0.0.
Note that we have already tried the following variations without success:
Not declaring the MultipartFilter in web.xml.
Not setting the resolver bean name for the MultipartFilter in web.xml.
Using the default resolver bean name filterMultipartResolver in webContext.xml.
UPDATE: I have confirmed that the documented behaviour does not work even with a single page sample app. Can anyone confirm that the documented behaviour works as expected? Is there an example working application that can be used?
I was able to resolve this with help from the Spring Security team. I have updated the Gist to reflect a working configuration. I had to follow the steps given below in order to get everything to work as expected.
1. Common Step
Add a MultipartFilter to web.xml as described in the answer by #holmis83, ensuring that it is added before the Spring Security configuration:
<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>
<filter>
<display-name>springSecurityFilterChain</display-name>
<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>
<dispatcher>ERROR</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
2.1. Using Apache Commons Multipart Resolver
Ensure that there is an Apache Commons Multipart Resolver bean named filterMultipartResolver in the root Spring application context. I will stress this again, make sure that the Multipart Resolver is declared in the root Spring Context (usually called applicationContext.xml). For example,
web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:springWebMultipartContext.xml
</param-value>
</context-param>
springWebMultipartContext.xml
<beans xmlns="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.xsd">
<bean id="filterMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="100000000" />
</bean>
</beans>
Make sure that the bean is called filterMultipartResolver as any other bean name is not picked up by MultipartFilter configured in web.xml. My initial configuration was not working because this bean was named multipartResolver. I even tried passing the bean name to MultipartFilter using web.xml init-param but that did not work either.
2.2. Using Tomcat Multipart support
Tomcat 7.0+ has in-built multipart support, but it has to be explicitly enabled. Either change the global Tomcat context.xml file as follows or include a local context.xml file in your WAR file for this support to work without making any other changes to your application.
<Context allowCasualMultipartParsing="true">
...
</Context>
After these changes using Apache Commons Multipart Resolver our application is working so far on Tomcat, Jetty and Weblogic.
This part:
<filter-mapping>
<filter-name>multipartFilter</filter-name>
<servlet-name>/*</servlet-name>
</filter-mapping>
Should be:
<filter-mapping>
<filter-name>multipartFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
It is an error in Spring Security 3.2.0 documentation. The bug has been reported and will be fixed in upcoming version.
After struggling with this issue a bit, I found a much easier solution by just using the Request Header defined in Spring Security instead of trying to get the CSRF token embedded as a part of the multipart content.
Here is a simple way I setup the header using an AJAX library for file upload in my jsp:
var uploader = new AjaxUpload({
url: '/file/upload',
name: 'uploadfile',
multipart: true,
customHeaders: { '${_csrf.headerName}': '${_csrf.token}' },
...
onComplete: function(filename, response) {
...
},
onError: function( filename, type, status, response ) {
...
}
});
Which in turn sent the multipart request with header:
X-CSRF-TOKEN: abcdef01-2345-6789-abcd-ef0123456789
Their recommendations for embedding into <meta /> tags in the header would also work just fine by halting the request on submit, adding the header via javascript, and then finish submitting:
<html>
<head>
<meta name="_csrf" content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf.headerName}"/>
<!-- ... -->
</head>
<body>
<!-- ... -->
<script>
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
// Do whatever with values
</script>
</body>
</html>
More info: Spring Security - CSRF for AJAX and JSON Requests
Find most answer is answered server years ago.
If you need
Passing CSRF tokens with RestTemplate
This blog is quite enlightening https://cloudnative.tips/passing-csrf-tokens-with-resttemplate-736b336a6cf6
In Spring Security 5.0.7.RELEASE
https://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html#csrf-multipart
There are two options to using CSRF protection with
multipart/form-data. Each option has its tradeoffs.
-Placing MultipartFilter before Spring Security
-Include CSRF token in
action
For short, the first option is safer, the latter is easier.
Specifying the MultipartFilter before the Spring Security filter
means that there is no authorization for invoking the MultipartFilter
which means anyone can place temporary files on your server. However,
only authorized users will be able to submit a File that is processed
by your application. In general, this is the recommended approach
because the temporary file upload should have a negligible impact on
most servers.
To ensure MultipartFilter is specified before the Spring Security
filter with java configuration, users can override
beforeSpringSecurityFilterChain as shown below:
public class SecurityApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
#Override
protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
insertFilters(servletContext, new MultipartFilter());
}
}
To ensure MultipartFilter is specified before the Spring Security
filter with XML configuration, users can ensure the
element of the MultipartFilter is placed before the
springSecurityFilterChain within the web.xml as shown below:
<filter>
<filter-name>MultipartFilter</filter-name>
<filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>MultipartFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Another option
If allowing unauthorized users to upload temporary files is not
acceptable, an alternative is to place the MultipartFilter after the
Spring Security filter and include the CSRF as a query parameter in
the action attribute of the form. An example with a jsp is shown below
<form action="./upload?${_csrf.parameterName}=${_csrf.token}" method="post" enctype="multipart/form-data">
The disadvantage to this approach is that query parameters can be
leaked. More genearlly, it is considered best practice to place
sensitive data within the body or headers to ensure it is not leaked.
I am working on a Spring application. I started from creating a small java app using spring. Later, it became necessary to add a web interface. I decided to use Spring MVC. Now I am confused. In my web.xml I have
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/mvc-dispatcher-servlet.xml,
/WEB-INF/applicationContext.xml
</param-value>
</context-param>
where mvc-dispacher-servlet.xml contains beans necessary for web logic while applicationContext.xml contains beans performing some specific operations. My question is: Are beans in these files going to be aware of each other? Is it going to be a one big container which includes beans from both config files? or these containers are separate?
Yes it will be in one context which will be loaded from the web application context. Its the same as you would do when using the application context and passing in multiple files to it.