Adding spring security to my current springmvc - spring

Sorry I'm rather new to Spring Security. I've got the following applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<!-- Activates various annotations to be detected in bean classes -->
<context:annotation-config />
<!-- Scans the classpath for annotated components that will be auto-registered as Spring beans.
For example #Controller and #Service. Make sure to set the correct base-package-->
<context:component-scan base-package="org.assessme.com" />
<!-- Configures the annotation-driven Spring MVC Controller programming model.
Note that, with Spring 3.0, this tag works in Servlet MVC only! -->
<mvc:annotation-driven />
</beans>
I'm following the tutorial on...
http://static.springsource.org/spring-security/site/tutorial.html
my question is, should I add to my existing applicationContext.xml or make a seperate XML file?
My web.xml is as follows...
<?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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
I'm a little bit confused as in the tutorial, it specifies the context-param of the xml but I already have one declared, can I have more that one context-param? If someone could give me an idea of the best way to use springmvc and spring security together that would be great as at the moment I'm finding it hard to "merge" the xml files.
Thanks,

You can have your security configuration in a separate file or combine with your existing application Context. If you want to use existing application context. You keep the default namespace as beans like this:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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-3.1.xsd">
<security:http auto-config="true">
<security:intercept-url pattern="/**" access="ROLE_USER" />
</security:http>
...
</beans>
and you have to prefix all security elements with security.
But if you define in separate files. The advantage is you can have security as the default namespace and omit the security prefix like this:
<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-3.1.xsd">
<http auto-config='true'>
<intercept-url pattern="/**" access="ROLE_USER" />
</http>
...
</beans:beans>
The common way is to define file names like this:
1)applicationContext.xml
2)applicationContext-security.xml
and in your web.xml like this:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
or as a comma or space separated list also like below:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml /WEB-INF/applicationContext-security.xml</param-value>
</context-param>
Documentation: ContextLoader
Documentation: namespace config

In the tutorial that you're following, it also uses:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext-business.xml
/WEB-INF/security-app-context.xml
</param-value>
</context-param>
in which applicationContext-business.xml is like your root-context.xml. So, you need to add the path to your Spring security configuration file. And, remember to also include the security filter mentioned in your web.xml.

Related

How to map the servlet to a child route(like /blog)?

I'm using SpringMVC and tomcat, and I want to assign all the URLs beginning with /blog to my servlet, here is my code.
web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
<display-name>Spring MVC XML Configuration Example</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:app-config.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>my-dispatcher-servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:web-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>my-dispatcher-servlet</servlet-name>
<url-pattern>/blog</url-pattern>
</servlet-mapping>
</web-app>
web-config.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd ">
<context:component-scan base-package="com.example" />
<mvc:annotation-driven />
<mvc:resources mapping="/blog/**" location="/WEB-INF/static/blog/" />
</beans>
app-config.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd ">
<context:component-scan base-package="com.example" />
</beans>
It doesn't work. I got a 404 when trying to access /blog/index.html. However, it worked if I changed the servlet-mapping part in web.xml to the following one.
<servlet-mapping>
<servlet-name>my-dispatcher-servlet</servlet-name>
<url-pattern>/</url-pattern> <!-- from /blog to / -->
</servlet-mapping>
But I don't want to do that, I only want the servlet to handle the URLs under /blog, can I do that? Should I change something in web-config.xml to make it work?
As mentioned by M.Deinum in the comments, I should change the servlet-mapping part in web.xml to the following one:
<servlet-mapping>
<servlet-name>my-dispatcher-servlet</servlet-name>
<url-pattern>/blog/*</url-pattern> <!-- notice the asterisk -->
</servlet-mapping>
Then change the mvc:resource part in web-config.xml to the following one.
<mvc:resources mapping="/**" location="/WEB-INF/static/blog/" />
It's done, now open /blog/index.html, it should work now.

404 error when spring security is added in the web.xml

I want to use Spring Security but I'm getting 404 error in the web.xml page after adding spring security tag in the web.xml page. If I remove the security tags in the web.xml then the .jsp pages are running the local host. I am unable to figure out the problem in the tags in the web.xml. Please help me in finding the problem. I have given all the XML codes.
Below is my code snippet from my project.
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"
id="WebApp_ID" version="3.0">
<display-name>Spring Web Application</display-name>
<!-- changed -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-dispatcher-servlet.xml,
/WEB-INF/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>
<servlet>
<servlet-name>spring-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>spring-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
This is my dispatcher.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:ctx="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd ">
<ctx:annotation-config></ctx:annotation-config>
<ctx:component-scan base-package="com.springMvc"></ctx:component-scan>
<ctx:component-scan base-package="com.springSecurity"></ctx:component-scan>
</beans:beans>
The spring security xml is given:
<?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:ctx="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.2.xsd">
<http>
<intercept-url pattern="/helloSecurity*" access="ROLE_USER" />
<http-basic/>
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="sjit" password="123" authorities="ROLE_USER"/>
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>

Defining beans for different modules of project

My project includes three modules:
koty-application (data access objects)
koty-domain (value objects - model)
koty-webapp (web application using Spring MVC)
I am using Gradle to build project - koty-application produces koty-application.jar, koty-domain produces koty-domain.jar and koty-webapp produces koty-webapp.war (which includes jars).
Temporarily, I defined beans only for koty-webapp module. The structure is like this:
web.xml:
<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">
<display-name>Baza danych kotow</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="pl.kobietydokodu" />
<context:annotation-config />
<mvc:annotation-driven />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
I defined beans for module koty-webapp and it works fine!
But I would like to define another beans for other module - for example KotyDAO for module koty-application. How should I define beans for koty-application module properly?
Full code of my project is here: https://github.com/evodv5/cats

contextLoaderListener configuration, controller not found

When I run my sample spring mvc webapplication with just DispatcherServlet it works fine but when I include ContextLoaderlListener also its trying to find controller class from applicationContext.xml which is actually defined in to scan in dispatcher-servlet.xml
Here is my web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/application-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>myapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/myapp-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>myapp</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Here is my application-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.startcompany.startapp">
<context:exclude-filter type="annotation" expression="com.startcompany.startapp.controller"/>
</context:component-scan>
</beans>
And this is myapp-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.startcompany.startapp.controller"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/views/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
getting this exception while deploying on tomcat.
SEVERE: Context initialization failed
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Type filter class not found: com.startcompany.startapp.controller; nested exception is java.lang.ClassNotFoundException: com.startcompany.startapp.controller
Offending resource: ServletContext resource [/WEB-INF/application-context.xml]; nested exception is java.lang.ClassNotFoundException: com.startcompany.startapp.controller
at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:70)
I think the problem is related with two contradictory statement in diff file.At one place you are trying to include the controller package for scanning and at other place you are excluding it.
application-context.xml
<context:exclude-filter type="annotation" expression="com.startcompany.startapp.controller"/>
myapp-servlet.xml
<context:component-scan base-package="com.startcompany.startapp.controller"/>
In exclude-filter, with type="annotation", you should use an annotation by which the excluded class is marked
expression="MyExcludingAnnotation"

Can I inject the WebApplicationContext of my Spring MVC servlet into a DelegatingFilterProxy?

I am creating an OAuth authorization server that uses Spring Security as my security layer around parts of my servlet. An essential part of this is using the DelegatingFilterProxy to map to the springSecurityFilterChain bean, which requires a WebApplicationContext instance.
The standard solution is to include a ContextLoaderListener with associated contextConfigLocation configuration. But that entails creating a separate configuration for the root WebApplicationContext, needlessly complicating matters in my opinion.
According to the Spring MVC documentation, every DispatcherServlet has it's own WebApplicationContext instance. What's more, from perusing the code of DelegatingFilterProxy, it should be possible to inject a WebApplicationContext instance at construction time.
So my question is: Can I set the DispatcherServlet WebApplicationContext as the instance for DelegatingFilterProxy?
Here is the relevant configuration I have currently:
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<!-- Enable Spring Security -->
<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>
<servlet>
<servlet-name>oauth</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>oauth</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/security/oauth2
http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<mvc:annotation-driven/>
<!-- ... Spring MVC config ... -->
<!-- Spring Security OAuth Config -->
<security:global-method-security pre-post-annotations="enabled" />
<oauth:authorization-server client-details-service-ref="clientDetails"
token-services-ref="tokenServices"
token-endpoint-url="/api/token">
<oauth:refresh-token/>
<oauth:client-credentials/>
</oauth:authorization-server>
<!-- ... loads more OAuth config ... -->
</beans>
DispatcherServlet (as any subclass of FrameworkServlet) will publish its WebApplicationContext in the ServletContext using the attribure name: org.springframework.web.servlet.FrameworkServlet.CONTEXT.<servlet-name>.
At the same time DelegatingFilterProxy can be told not to use the root WebApplicationContext but another one stored in the ServletContext by setting its contextAttribute parameter.
In your case the required config would be:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.oauth </param-value>
</init-param>
</filter>
See more about how DelegatingFilterProxy looks up the WebApplicationContext in the javadoc of findWebApplicationContext().

Resources