04 November 2017

Spring security application with password hashing

Spring security framework provides solutions for developing applications with authorization and authentication.We use password encoder in with this example.

To build Spring MVC based web application,which uses Spring Security framework for login,
We need
1.JDK
2.Apache Maven
3.Intellij/Eclipse(Editor tool)
4.Apache Tomcat

We have developed a sample Spring MVC application in this link.
Project structure look like



DelegatingFilterProxy is an impelmentation of the javax.servlet.Servlet filters can intercept requests before reaching servlet.
We have to configure this DelegatingFilterProxy in web.xml,it acts as filter.
We have to define a spring spring-security.xml  in context param.
web.xml :

<?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">


    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/java9pro-springmvc-servlet.xml
        /WEB-INF/java9pro-security.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
    </listener>
    <servlet>
        <servlet-name>java9pro-springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>java9pro-springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <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>


</web-app>

We have to define a  spring-security.xml .Spring security framework provides BCryptPasswordEncoder to hash the passwords.
So the hashed password for java9pro is  $2a$10$p.r1COYmT0kl8iU3Eq56EeCm1.QdcwIRozzkJ5GVOLxAGICAxCLIy.
Same has been provided as password for user java9pro.
Following util class can be used to generate the hashed password.

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

public class Utils {
    public static void main(String[] args) {
            String password = "java9pro";
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
         System.out.println(passwordEncoder.encode(password));

        }
}

http configuration is used to intercept the url access along with the role.
authentication manager configuration consists of  user service configuration to fetch the user credentials to authenticate the application.
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"       xmlns="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.2.xsd       http://www.springframework.org/schema/security       http://www.springframework.org/schema/security/spring-security-3.2.xsd ">

    <http auto-config="true">
        <intercept-url pattern="/login" access="ROLE_USER" />
    </http>

    <authentication-manager>
        <authentication-provider>
            <password-encoder ref="passwordEncoder"/>
            <user-service>
                <user name="java9pro" 
password="$2a$10$p.r1COYmT0kl8iU3Eq56EeCm1.QdcwIRozzkJ5GVOLxAGICAxCLIy"
 authorities="ROLE_USER" />
            </user-service>
        </authentication-provider>
    </authentication-manager>
    <beans:bean id="passwordEncoder" 
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
        <beans:constructor-arg name="strength" value="11" />
    </beans:bean>

</beans:beans>

 pom.xml:

Add  below jars
spring-security-core
spring-security-config
spring-security-web

<?xml version="1.0" encoding="UTF-8"?>
<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>java9pro.springmvc</groupId>
    <artifactId>java9pro.springmvc.arti</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
    <build>
        <finalName>springJava9ProMVC</finalName>
    </build>

    <dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.3.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.3.2.RELEASE</version>
    </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-crypto</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>

    </dependencies>


</project>

Controller Class Java9ProController looks like
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controllerpublic class Java9ProController {
    @RequestMapping("/login")
    public String loginPage(){
        return "login";
    }

    @RequestMapping("/")
    public String logoutPage(){

        return "logout";
    }

}

Spring MVC bean confiuration file java9pro-springmvc-servlet.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/mvc 
http://www.springframework.org/schema/mvc/spring-mvc.xsd      
 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.becomeJavaPro.springmvc"/>
    <mvc:annotation-driven/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

</beans>


Spring Security will automatically create a login URL at /spring_security_login


When Username as java9pro and Password as java9pro


When bad credentials