Wednesday, June 26, 2013

Spring Security: JDBC + Customized 403 & Login Form



Let’s start building the spring security application:

Basic Requirement :

 Create two tables in MYSQL :



CREATE TABLE `users` (

  `USER_ID` INT(10) UNSIGNED NOT NULL,

  `USERNAME` VARCHAR(45) NOT NULL,

  `PASSWORD` VARCHAR(45) NOT NULL,

  `ENABLED` tinyint(1) NOT NULL,

  PRIMARY KEY (`USER_ID`)

);



CREATE TABLE `user_roles` (

  `USER_ROLE_ID` INT(10) UNSIGNED NOT NULL,

  `USER_ID` INT(10) UNSIGNED NOT NULL,

  `AUTHORITY` VARCHAR(45) NOT NULL,

  PRIMARY KEY (`USER_ROLE_ID`),

  KEY `FK_user_roles` (`USER_ID`),

  CONSTRAINT `FK_user_roles` FOREIGN KEY (`USER_ID`) REFERENCES `users` (`USER_ID`) ON DELETE CASCADE

);

Insert values :
INSERT INTO testdb1.users (USER_ID, USERNAME,PASSWORD, ENABLED)

VALUES (100, 'kumar', 'kumar', TRUE);



INSERT INTO testdb1.user_roles (USER_ROLE_ID, USER_ID,AUTHORITY)

VALUES (1, 100, 'ROLE_USER');



INSERT INTO testdb1.users (USER_ID, USERNAME,PASSWORD, ENABLED)

VALUES (200, 'sushil', 'sushil', TRUE);



INSERT INTO testdb1.user_roles (USER_ROLE_ID, USER_ID,AUTHORITY)

VALUES (2, 200, 'ROLE_ADMIN');

Code Structure in Eclipse

 


LoginController.java:
package com.sushil.spring.security.controller;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class LoginController {

       @RequestMapping(value="/welcome", method = RequestMethod.GET)
       public String printWelcome(ModelMap model) {

       User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
              String name = user.getUsername();
              System.out.println("in Welcome module");
              model.addAttribute("username", name);
              model.addAttribute("message", "Spring Security login + database example");
              return "hello";
       }

       @RequestMapping(value="/login", method = RequestMethod.GET)
       public String login(ModelMap model) {
              System.out.println("in login module");
              return "login";
       }
      
       @RequestMapping(value="/loginfailed", method = RequestMethod.GET)
       public String loginerror(ModelMap model) {
              System.out.println("in login failed module");
              model.addAttribute("error", "true");
              return "login";
       }
      
       @RequestMapping(value="/logout", method = RequestMethod.GET)
       public String logout(ModelMap model) {
              return "login";
       }
      
       @RequestMapping(value="/403", method = RequestMethod.GET)
       public String accessDenied(){
              return "403";
       }
}

login.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Login Page</title>
<style>
.errorblock {
       color: #ff00cc;
       background-color: #ffEEEE;
       border: 10px solid #ff0000;
       padding: 10px;
       margin: 20px;
}
</style>
</head>
<body onload='document.f.j_username.focus();'>
       <h3>Login Authentication with Database</h3>

       <c:if test="${not empty error}">
              <div class="errorblock">
                     Your login attempt was not successful, try again.<br />
Caused : ${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}
              </div>
       </c:if>

       <form name='f' action="<c:url value='j_spring_security_check' />"
              method='POST'>
              <table border="2">
                     <tr>
                           <td colspan="2">User:</td>
                           <td></td>
                           <td><input type='text' name='j_username' value=''>
                           </td>
                     </tr>
                     <tr>
                           <td colspan="2">Password:</td>
                           <td></td>
                           <td><input type='password' name='j_password' />
                           </td>
                     </tr>
                     <tr>
                           <td colspan='2'><input name="submit" type="submit"
                                  value="submit" />
                           </td>
                           <td></td>
                           <td colspan='1'><input name="reset" type="reset" />
                           </td>
                     </tr>
                     <tr> </tr>
              </table>
       </form>
</body>
</html>

hello.jsp:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
       <h3>Message : ${message}</h3>    
       <h3>Username : ${username}</h3>  
       <a href="<c:url value="/j_spring_security_logout" />" > Logout</a>
</body>
</html>

403.jsp:

<html>
<body>
       <h1><font color="red">WARNING : ${msg}</font></h1>           
</body>
</html>


SpringMvcSecurityDatabase-servlet.xml

<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-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="com.sushil.spring.security.controller" />


       <bean id="accessDeniedHandler" 
class="com.sushil.spring.security.handler.MyAccessDeniedHandler">
              <property name="accessDeniedUrl" value="403" />
   </bean>
  
   <bean id="dataSource"
              class="org.springframework.jdbc.datasource.DriverManagerDataSource">
              <property name="driverClassName" value="com.mysql.jdbc.Driver" />
              <property name="url" value="jdbc:mysql://localhost:3306/testdb1" />
              <property name="username" value="root" />
              <property name="password" value="admin" />
       </bean>
  
       <bean
              class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <property name="prefix">
                     <value>/WEB-INF/pages/</value>
              </property>
              <property name="suffix">
                     <value>.jsp</value>
              </property>
       </bean>

       <bean id="messageSource"
              class="org.springframework.context.support.ResourceBundleMessageSource">
              <property name="basenames">
                     <list>
                           <value>mymessages</value>
                     </list>
              </property>
       </bean>
      
</beans>

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 pattern="/welcome*" access="ROLE_ADMIN" />
              <form-login login-page="/login" default-target-url="/welcome" authentication-failure-url="/loginfailed" />
              <logout logout-success-url="/logout" />
              <access-denied-handler ref="accessDeniedHandler"/>
       </http>

       <authentication-manager>
              <authentication-provider>
                     <jdbc-user-service data-source-ref="dataSource"
                        users-by-username-query="select username,password, enabled
                                  from users where USERNAME=?"
                                 authorities-by-username-query=" select u.username, ur.authority from users u, user_roles ur where u.user_id = ur.user_id and u.username =?  " />
              </authentication-provider>
       </authentication-manager>
</beans:beans>

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/j2ee" xmlns:javaee="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/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" id="WebApp_ID" version="2.4">
  <display-name>Spring MVC + Security Application</display-name>
  <servlet>
    <servlet-name>SpringMvcSecurityDatabase</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>SpringMvcSecurityDatabase</servlet-name>
    <url-pattern>/</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/SpringMvcSecurityDatabase-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>
</web-app>

Output Screens :


Just hit ‘http://localhost:8080/Example2/welcome’ on the browser :

Customized login form :




 
Enter Wrong Password / login name


 Enter authorized user name and password 'sushil' , 'sushil'

Enter UnAuthorized user details 'kumar' , 'kumar'




Spring Security: Spring MVC 3.0 + Spring Security 3.1



After so many days I am back again with some new and hot topic:-

Spring Security 3.1  :

As software developers, we must take steps to protect the information that resides in our applications. Whether it’s an email account protected with a username/pass- word pair or a brokerage account protected with a trading PIN, security is a crucial aspect of most applications.

                        Spring Security is a security framework that provides declarative security for your Spring-based applications. Spring Security provides a comprehensive security solution, handling authentication and authorization at both the web request level and at the method invocation level.


No matter what kind of application you want to secure using Spring Security, the first thing to do is to add the Spring Security modules to the application’s classpath. you’ll want to include the Spring-Core.3.1.1.jar and Spring-Config.3.1.1.jar modules in your application’s classpath. Spring Security is often used to secure web applications. That’s certainly the case with our Hello World MVC application, so we’ll also need to add the Spring-web.3.1.1.jar module.


Let’s Start building the spring security application :
 

Code Structure in Eclipse



 HelloController.java

package com.sushil.spring.security.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

@Controller
@RequestMapping("/hello")
public class HelloController {

       @RequestMapping(method = RequestMethod.GET)
       public String printWelcome(ModelMap model) {
              model.addAttribute("message", "learning Spring Security is DAMN Easy");
              return "hello";
       }
}

hello.jsp

<html>
<body>
       <h1>Sushil Spring Tutorials</h1>
       <h3>${message}</h3> 
</body>
</html>

springMvcSecurity-servlet.xml

<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-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="com.sushil.spring.security.controller" />

       <bean
              class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <property name="prefix">
                     <value>/WEB-INF/pages/</value>
              </property>
              <property name="suffix">
                     <value>.jsp</value>
              </property>
       </bean>
</beans>

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 pattern="/hello*" access="ROLE_ADMIN" />
       </http>

       <authentication-manager>
              <authentication-provider>
                     <user-service>
                           <user name="sushil" password="sushil" authorities="ROLE_ADMIN" />
                     </user-service>
              </authentication-provider>
       </authentication-manager>
</beans:beans>


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>Spring MVC Application</display-name>

       <!-- Spring MVC -->
       <servlet>
              <servlet-name>springMvcSecurity</servlet-name>
              <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
              <load-on-startup>1</load-on-startup>
       </servlet>
       <servlet-mapping>
              <servlet-name>springMvcSecurity</servlet-name>
              <url-pattern>/</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/springMvcSecurity-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>

</web-app>

Output Screens :
 
 Just hit ‘http://localhost:8080/Example1/hello’ on the browser :



In case you enter wrong username/password



Once you properly enter username and password, ‘sushil’ and ‘sushil’, you will get