In this post I write about a basic configuration of Spring Security 3, the Spring framework for authentication and authorization of the users.
In this example there is only one user trying to access to index.html and he is redirected to the standard login page for authentication.
In this project I use and configure maven and log4j too.
- create the project SpringSecurity
- create the file pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>SpringSecurity</groupId> <artifactId>SpringSecurity</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <!-- Shared version number properties --> <properties> <org.springframework.version>3.1.1.RELEASE</org.springframework.version> <log4j.version>1.2.17</log4j.version> <jstl.version>1.2</jstl.version> </properties> <dependencies> <!-- Core utilities used by other modules. Define this if you use Spring Utility APIs (org.springframework.core.*/org.springframework.util.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Expression Language (depends on spring-core) Define this if you use Spring Expression APIs (org.springframework.expression.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Bean Factory and JavaBeans utilities (depends on spring-core) Define this if you use Spring Bean APIs (org.springframework.beans.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Aspect Oriented Programming (AOP) Framework (depends on spring-core, spring-beans) Define this if you use Spring AOP APIs (org.springframework.aop.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Application Context (depends on spring-core, spring-expression, spring-aop, spring-beans) This is the central artifact for Spring's Dependency Injection Container and is generally always defined --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Various Application Context utilities, including EhCache, JavaMail, Quartz, and Freemarker integration Define this if you need any of these integrations --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Transaction Management Abstraction (depends on spring-core, spring-beans, spring-aop, spring-context) Define this if you use Spring Transactions or DAO Exception Hierarchy (org.springframework.transaction.*/org.springframework.dao.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- JDBC Data Access Library (depends on spring-core, spring-beans, spring-context, spring-tx) Define this if you use Spring's JdbcTemplate API (org.springframework.jdbc.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Object-to-Relation-Mapping (ORM) integration with Hibernate, JPA, and iBatis. (depends on spring-core, spring-beans, spring-context, spring-tx) Define this if you need ORM (org.springframework.orm.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Object-to-XML Mapping (OXM) abstraction and integration with JAXB, JiBX, Castor, XStream, and XML Beans. (depends on spring-core, spring-beans, spring-context) Define this if you need OXM (org.springframework.oxm.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-oxm</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Web application development utilities applicable to both Servlet and Portlet Environments (depends on spring-core, spring-beans, spring-context) Define this if you use Spring MVC, or wish to use Struts, JSF, or another web framework with Spring (org.springframework.web.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Spring MVC for Servlet Environments (depends on spring-core, spring-beans, spring-context, spring-web) Define this if you use Spring MVC with a Servlet Container such as Apache Tomcat (org.springframework.web.servlet.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Spring MVC for Portlet Environments (depends on spring-core, spring-beans, spring-context, spring-web) Define this if you use Spring MVC with a Portlet Container (org.springframework.web.portlet.*) --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc-portlet</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- Support for testing Spring applications with tools such as JUnit and TestNG This artifact is generally always defined with a 'test' scope for the integration testing framework and unit testing stubs --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${org.springframework.version}</version> <scope>test</scope> </dependency> <!-- log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <!-- Spring Security --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>${org.springframework.version}</version> </dependency> <!-- JSTL --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <!-- spring security tag --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-taglibs</artifactId> <version>${org.springframework.version}</version> </dependency> </dependencies> </project>
In the section “properties” I set the versions of the dependencies; in the comments you read the name of the dependencies: the first part covers the Spring Framework, followed by Log4j for log management, Spring Security for authentication and authorization of the users, jstl or java standard tag library to use the tag “c” (for example <c:if>) and spring security tags to use the tag “sec” (for example <sec:authorize>);
alternatively you can copy the following files. jar in the directory WEB-INF/lib- spring-core-3.1.1.RELEASE.jar
- spring-asm-3.1.1.RELEASE.jar
- commons-logging-1.1.1.jar
- spring-expression-3.1.1.RELEASE.jar
- spring-beans-3.1.1.RELEASE.jar
- spring-aop-3.1.1.RELEASE.jar
- aopalliance-1.0.jar
- spring-context-3.1.1.RELEASE.jar
- spring-context-support-3.1.1.RELEASE.jar
- spring-tx-3.1.1.RELEASE.jar
- spring-jdbc-3.1.1.RELEASE.jar
- spring-orm-3.1.1.RELEASE.jar
- spring-oxm-3.1.1.RELEASE.jar
- commons-lang-2.5.jar
- spring-web-3.1.1.RELEASE.jar
- spring-webmvc-3.1.1.RELEASE.jar
- spring-webmvc-portlet-3.1.1.RELEASE.jar
- spring-test-3.1.1.RELEASE.jar
- log4j-1.2.17.jar
- spring-security-core-3.1.1.RELEASE.jar
- spring-security-web-3.1.1.RELEASE.jar
- spring-security-config-3.1.1.RELEASE.jar
- jstl-1.2.jar
- spring-security-taglibs-3.1.1.RELEASE.jar
- spring-security-acl-3.1.1.RELEASE.jar
- create the file WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5" 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_2_5.xsd" > <display-name> SpringSecurity </display-name> <!-- Spring MVC --> <servlet> <servlet-name> SpringSecurity </servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup> 1 </load-on-startup> </servlet> <servlet-mapping> <servlet-name> SpringSecurity </servlet-name> <url-pattern> *.html </url-pattern> </servlet-mapping> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <context-param> <param-name> contextConfigLocation </param-name> <param-value> /WEB-INF/SpringSecurity-servlet.xml /WEB-INF/spring-security.xml </param-value> </context-param> <!-- 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> <!-- Log4j --> <context-param> <param-name> log4jConfigLocation </param-name> <param-value> /WEB-INF/log4j.xml </param-value> </context-param> <listener> <listener-class> org.springframework.web.util.Log4jConfigListener </listener-class> </listener> <session-config> <session-timeout> 30 </session-timeout> </session-config> <welcome-file-list> <welcome-file> index.html </welcome-file> </welcome-file-list> </web-app>
You can see the reference to /WEB-INF/spring-security.xml and the sections “filter” and “filter-mapping” to configure Spring Security
- create the file WEB-INF/SpringSecurity-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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" 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"> <context:component-scan base-package="eu.lucazanini.springsecurity" /> <bean id="viewResolver" 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>
- create the file WEB-INF/log4j.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration PUBLIC "-//LOGGER" "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="stdout" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %-5p %c{1}:%L %m %n" /> <!-- ConversionPattern format specification %d inserts the date; you can specify the format (%d{yyyy-MM-dd HH:mm:ss,SSS}) %-5p inserts the priority log level, 5 characters, left justified %c{1} inserts the name of the class %L inserts the line number %m inserts the user message %n inserts the separator (for example, a new line) --> </layout> </appender> <appender name="fileAppender" class="org.apache.log4j.RollingFileAppender"> <param name="Threshold" value="INFO" /> <param name="MaxFileSize" value="512KB" /> <param name="MaxBackupIndex" value="10" /> <param name="File" value="${webapp.root}/WEB-INF/logs/springsecurity.log"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %-5p %c{1}:%L %m %n" /> </layout> </appender> <!--sets the priority log level for org.springframework--> <logger name="org.springframework"> <level value="info"/> </logger> <!--sets the priority log level for eu.lucazanini.springsecurity--> <logger name= "eu.lucazanini.springsecurity"> <level value="debug"/> </logger> <!--sets the default priority log level--> <root> <priority value="info"></priority> <appender-ref ref="stdout"/> <appender-ref ref="fileAppender"/> </root> </log4j:configuration>
- create the file WEB-INF/spring-security.xml
<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 access="ROLE_USER" pattern="/**" /> </http> <beans:bean id="encoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder" /> <authentication-manager> <authentication-provider> <password-encoder ref="encoder" /> <user-service> <user name="user" authorities="ROLE_USER" password="20331ba9c4935517ab16f0052097b0d79f40f0a54a1a025ec742a308e8564757e021797bf7185332" /> </user-service> </authentication-provider> </authentication-manager> </beans:beans>
The password is encrypted using Scala
I write the procedure to get the encrypted password:- download spring-security-core-*.jar (for example spring-security-core-3.1.1.RELEASE.jar) in the last release of Spring Security
- install Scala
- open a console and type:
scala -cp [your path]/spring-security-core-3.1.1.RELEASE.jar
where [your path] è is the path to spring-security-core-3.1.1.RELEASE .jar
(the output should be:
Welcome to Scala version 2.9.1.r0-b20120114224707 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_05).
Type in expressions to have them evaluated.
Type :help for more information.) - type:
val encoder = new org.springframework.security.crypto.password.StandardPasswordEncoder
Output:
encoder: org.springframework.security.crypto.password.StandardPasswordEncoder = org.springframework.security.crypto.password.StandardPasswordEncoder@448d5117 - type:
encoder.encode("spring")
Output:
res0: java.lang.String = 20331ba9c4935517ab16f0052097b0d79f40f0a54a1a025ec742a308e8564757e021797bf7185332
the sequence of charachters after “res0: java.lang.String =” is just the encrypted password in the file spring-security.xml
- create the file WEB-INF/views/index.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %> <html> <body> <h1>Spring Security basic configuration</h1> <h3><br />Hello ${username}, ${message}</h3> <sec:authorize ifAnyGranted="ROLE_USER"> <h6><br />Your role is ROLE_USER</h6> </sec:authorize> <input type="button" value="Log out" onClick="location.href='<c:url value="/j_spring_security_logout" />'"/> </body> </html>
I set the variables ${message} and ${username} in LoginController.java; the button is just a link to /j_spring_security_logout and allows the user to log out
- create the file WEB-INF/classes/eu/lucazanini/springsecurity/LoginController.java
package eu.lucazanini.springsecurity; import java.security.Principal; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.apache.log4j.Logger; @Controller public class LoginController { private static org.apache.log4j.Logger log = Logger .getLogger(LoginController.class); @RequestMapping(value = "/index", method = RequestMethod.GET) public String printWelcome(ModelMap model, Principal principal) { log.debug("LoginController"); String name = principal.getName(); model.addAttribute("username", name); model.addAttribute("message", "you are logged in"); return "index"; } }
- launch the application (type “user” and “spring”)
References:
Spring Security
Leave a Reply