Sunday, 22 November 2015

Spring Security 4 Login Example using Hibernate & Annotations without using XML Configuration

Hi,

I faced some difficulties while setting up login using Spring Security 4 login without XML configuration. I thought of writing it, so others can refer and save time while developing.

Environment used
  • IDE: STS
  • Database: MySql 
  • Project Management: Maven
  • Server: Jetty (Default Server looks for Web.xml)
ImportantJAR's used
  • Jackson JSON Mapper JAR version 1.9.10
  • Spring Security JAR version 4.0.2 (Web,Config,Data & Taglibs)
  • Spring webMVC JAR
  • JPA, Spring Data, HSQL, MySQL JAR's
  • Other Web Dependency JAR's
STS latest release is 3.7.1 it will create web.xml file for Spring project by default. So use 
File->New->Maven Project. It won't create web.xml

Add the above mentioned JAR's to POM.

I have explained Security Config and CustomAuthenticationProvider class here, get whole project from GIT.

SecurityConfig.java
 package com.springsecurityblog.config;  
 /**  
  * Author: Ramakrishna Panni  
  * Class: SecurityConfig  
  * Details: It does configure for Login page, Logout page, Failure page and CSRF token management  
  */  
 import org.springframework.beans.factory.annotation.Autowired;  
 import org.springframework.context.annotation.Bean;  
 import org.springframework.context.annotation.Configuration;  
 import org.springframework.security.authentication.AuthenticationManager;  
 import org.springframework.security.authentication.AuthenticationProvider;  
 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;  
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;  
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;  
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;  
 import org.springframework.security.data.repository.query.SecurityEvaluationContextExtension;  
 import org.springframework.security.web.csrf.CsrfTokenRepository;  
 import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;  
 @Configuration  
 @EnableWebSecurity  
 public class SecurityConfig extends WebSecurityConfigurerAdapter{  
   @Autowired  
   private AuthenticationProvider customAuthenticationProvider;   
      @Autowired  
      public void configure(AuthenticationManagerBuilder auth) throws Exception {  
            auth  
            .authenticationProvider(customAuthenticationProvider);  
   }  
       @Override  
        protected void configure(HttpSecurity http) throws Exception {  
          http.authorizeRequests().antMatchers("/assets/**").permitAll()  
          .and()  
            .formLogin().loginPage("/loginPage")  
              .defaultSuccessUrl("/homePage")  
              .failureUrl("/loginPage?error")  
              .usernameParameter("username").passwordParameter("password")     
              .and().csrf().csrfTokenRepository(csrfTokenRepository())  
            .and()  
              .logout().logoutSuccessUrl("/loginPage?logout");   
        }  
   @Bean  
   public SecurityEvaluationContextExtension securityEvaluationContextExtension() {  
     return new SecurityEvaluationContextExtension();  
   }  
   @Override  
   public AuthenticationManager authenticationManagerBean() throws Exception {  
    return super.authenticationManagerBean();  
   }  
   private CsrfTokenRepository csrfTokenRepository()   
   {   
     HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();   
     repository.setSessionAttributeName("_csrf");  
     return repository;   
   }  
 }  

What does Security Config do?

It  configures Authentication provider of configure method where the Role and Authentication of request is done. It does http security configuration with which URL to permit, login URL's and it also configures whether the application needs CSRF token generation. We can configure Success handlers for login and others here too. It extends "WebSecurityConfigurerAdapter" of Spring Framework Security.

CustomAuthenticationProvider.java
 package com.springsecurityblog.config;  
 /**  
  * Author: Ramakrishna Panni  
  * Class: CustomAuthenticationProvider  
  * Details: It is used to get credentials and authorize the request with roles  
  */  
 import java.util.HashSet;  
 import java.util.Set;  
 import org.springframework.beans.factory.annotation.Autowired;  
 import org.springframework.security.authentication.AuthenticationProvider;  
 import org.springframework.security.authentication.BadCredentialsException;  
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;  
 import org.springframework.security.core.Authentication;  
 import org.springframework.security.core.AuthenticationException;  
 import org.springframework.security.core.GrantedAuthority;  
 import org.springframework.security.core.authority.SimpleGrantedAuthority;  
 import org.springframework.stereotype.Component;  
 import com.springsecurityblog.model.Employee;  
 import com.springsecurityblog.model.Role;  
 import com.springsecurityblog.service.AccountService;  
 @Component("AuthenticationProvider")  
 public class CustomAuthenticationProvider implements AuthenticationProvider {  
       @Autowired  
       private AccountService accountService;  
       public Authentication authenticate(Authentication authentication)   
           throws AuthenticationException {  
                      String username = authentication.getName();  
                      String password = (String) authentication.getCredentials();  
            Employee member = accountService.findAccountByUsername(username);  
            //For username not valid   
         if (member == null || !member.getEmployeeUserName().equalsIgnoreCase(username)) {  
           throw new BadCredentialsException("Username not found.");  
         }  
         //For password not valid  
         if (!password.equals(member.getPassword())) {  
           throw new BadCredentialsException("Wrong password.");  
         }  
         Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();  
         //Employee can have many roles  
         for (Role employeeRole : member.getEmpRoles()) {  
                    setAuths.add(new SimpleGrantedAuthority(employeeRole.getAuthority()));  
               }  
         return new UsernamePasswordAuthenticationToken(member, password, setAuths);   
          }  
           public boolean supports(Class<?> authentication) {  
                   return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));  
                }  
 }  

What does CustomAuthenication Provider do?
Here we will get the login credential entered, which is captured by SecurityConfig class. By using Service methods we can get to know whether the credential is correct or wrong. Roles extends Authority, there can be many roles.

Here is the table created for Employee and Role Bean.


 CREATE TABLE `tblemployee` (  
   `ntEmpID` bigint(20) NOT NULL AUTO_INCREMENT,  
   `vcEmployeeUserName` varchar(30) NOT NULL,  
   `vcEmailIdOff` varchar(50) NOT NULL,  
   `vcEmailIdPer` varchar(50) NOT NULL,  
   `vcEmployeeFirstName` varchar(30) NOT NULL,  
   `vcEmployeeMiddleName` varchar(30) DEFAULT NULL,  
   `vcEmployeeLastName` varchar(30) NOT NULL,  
   `vcPresentAdd` varchar(150) NOT NULL,  
   `vcPermanentAdd` varchar(150) NOT NULL,  
   `vcHomePhoneNumber` varchar(10) DEFAULT NULL,  
   `vcOfficeNumber` varchar(10) NOT NULL,  
   `vcSkills` varchar(100) DEFAULT NULL,  
   `vcPassword` varchar(4000) NOT NULL,  
   `fsCV` tinyblob,  
   `fsEmployeePic` tinyblob,  
   PRIMARY KEY (`ntEmpID`),  
   UNIQUE KEY `UQ__tblEmplo__993FFD3B15DA3E5D` (`vcEmailIdPer`),  
   UNIQUE KEY `UQ__tblEmplo__96FFB61918B6AB08` (`vcEmailIdOff`),  
   UNIQUE KEY `UQ__tblEmplo__ED923BE51B9317B3` (`vcEmployeeUserName`)  
  ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1  
 CREATE TABLE `tblemproles` (  
   `ntEmpRoleID` bigint(20) NOT NULL AUTO_INCREMENT,  
   `ntEmpID` bigint(20) NOT NULL,  
   `vcRole` varchar(45) NOT NULL,  
   PRIMARY KEY (`ntEmpRoleID`),  
   UNIQUE KEY `uni_empID_role` (`vcRole`,`ntEmpID`),  
   KEY `ntEmpID` (`ntEmpID`),  
   CONSTRAINT `tblemproles_ibfk_1` FOREIGN KEY (`ntEmpID`) REFERENCES `tblemployee` (`ntEmpID`) ON DELETE NO ACTION ON UPDATE NO ACTION  
  ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1  
loginPage.jsp


 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>  
 <html>  
 <head>  
      <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.3.min.js"></script>  
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.1/angular.min.js"></script>  
 </head>  
 <body ng-app='Login' onload='document.loginForm.username.focus();'>  
   <h3>TMS</h3>  
   <c:if test="${not empty error}"><div>${error}</div></c:if>  
   <c:if test="${not empty message}"><div>${message}</div></c:if>  
   <form name='login' action="<c:url value='/loginPage' />" method='POST'>  
     <table>  
       <tr>  
         <td>UserName:</td>  
         <td><input type='text' name='username' ng-model="login.username" value=''></td>  
       </tr>  
       <tr>  
         <td>Password:</td>  
         <td><input type='password' name='password' ng-model="login.password" /></td>  
       </tr>  
       <tr>  
         <td colspan='2'><button type="submit">Submit</button></td>  
       </tr>  
     </table>  
     <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />  
   </form>  
 </body>  
 </html>  
homePage.jsp


 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>  
 <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>  
 <%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec"%>  
 <!DOCTYPE html>  
 <html>  
 <head>  
  <meta charset="utf-8">  
  <meta http-equiv="X-UA-Compatible" content="IE=edge">  
  <meta name="_csrf" content="${_csrf.token}"/>  
      <!-- default header name is X-CSRF-TOKEN -->  
      <meta name="_csrf_header" content="${_csrf.headerName}"/>  
      <!-- ... -->  
  <title>Home</title>  
  <!-- Tell the browser to be responsive to screen width -->  
  <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">  
  <!-- Bootstrap 3.3.5 -->  
  <!--Favicon Image -->  
 </head>  
 <body class="hold-transition skin-blue sidebar-mini">  
 <sec:authorize access="hasRole('ANONYMOUS')">  
      <c:redirect url="/loginPage"/>  
 </sec:authorize>  
 <p>Welcome, <sec:authentication property="principal.employeeUserName"/></p><br/>  
 <c:url value="/logout" var="Signout" />  
      <form id="logout" action="${Signout}" method="post" >  
            <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />  
      </form>  
 </body>  
 </html>  
After Login
We land in Home page. There we can get all values through "principal"object using Security tags.

Thanks,

Monday, 2 November 2015

Spiral Value Assigned Matrix

Hi,


I got a question from my friend, if user gives input 6 or  any number it should show matrix in the form of normal and Spiral assigned values.

Matrix Size is: 6

Normal Matrix is:

    1    2    3    4    5    6
    7    8    9   10   11   12
   13   14   15   16   17   18
   19   20   21   22   23   24
   25   26   27   28   29   30
   31   32   33   34   35   36
Spiral Matrix is:

    1     2        3     4      5      6
   20    21    22    23    24     7
   19    32    33    34    25     8
   18    31    36    35    26     9
   17    30    29    28    27    10
   16    15    14    13    12    11

I had gone through the problem, got it can be solved in 4 recurring  steps.

 package newlearn;  
 import java.util.Scanner;  
 /**  
  *   
  * @author Ramakrishna Panni  
  *  
  */  
 public class SpiralMatrix {  
      public static void main(String[] args) {  
           // TODO Auto-generated method stub  
           try{  
                System.out.println("Enter matrix size to get spiral matrix");  
                Scanner sc = new Scanner(System.in);  
                String[] inter = sc.nextLine().trim().split(" ");  
                int size = Integer.parseInt(inter[0]);  
                System.out.println("Matrix Size is: "+size);  
                sc.close();  
                int higestValue = size*size;  
                int spiralMatrix[][] = new int[size][size];  
                int normalMatrix[][] = new int[size][size];  
                int normalValue = 0;  
                for(int i=0;i<size;i++)  
                {  
                     for(int j=0;j<size;j++)  
                     {  
                          normalMatrix[i][j] = ++normalValue;  
                          spiralMatrix[i][j] = 0;  
                     }  
                }  
                System.out.println("Normal Matrix is:\n");  
                for(int i=0;i<size;i++)  
                {  
                     for(int j=0;j<size;j++)  
                     {  
                          System.out.printf("%5d",normalMatrix[i][j]);  
                     }  
                     System.out.println("");  
                }  
                int lastValue=0;  
                int step = 1;  
                int step1Col = 0;  
                int step1Row = 0;  
                int step2Col = 0;  
                int step2Row = 0;  
                int step3Col = 0;  
                int step3Row = 0;  
                int step4Col = -1;  
                int step4Row = 0;  
                while (lastValue < higestValue) {  
                     step = 1;  
                     //this is the step where value assigned in Horizontal incrementing positional way  
                     if(step == 1)  
                     {  
                          step1Row = step4Row;  
                          step1Col = ++step4Col;  
                          for(int j=step1Col;j<size;j++)  
                          {  
                               if(spiralMatrix[step1Row][j] == 0)  
                               {  
                                    spiralMatrix[step1Row][j] = ++lastValue;  
                                    step1Col = j;  
                               }  
                               else{  
                                    break;  
                               }  
                          }  
                          step = ++step;  
                     }  
                     //this is the step where value assigned in Vertical incrementing positional way  
                      if (step == 2)  
                     {  
                          step2Col = step1Col;  
                          step2Row = step1Row+1;  
                          for(int i=step2Row;i<size;i++)  
                          {  
                               if(spiralMatrix[i][step1Col] == 0)  
                                    {  
                                         spiralMatrix[i][step1Col] = ++lastValue;  
                                         step2Row = i;  
                                    }  
                                    else{  
                                         break;  
                                    }  
                          }  
                          step = ++step;  
                     }  
                     //this is the step where value assigned in Horizontal decrementing positional way  
                      if(step==3)  
                     {  
                          step3Row = step2Row;  
                          step3Col = step2Col-1;  
                               for(int j=step3Col;j>=0;j--)  
                               {  
                                    if(spiralMatrix[step3Row][j] == 0)  
                                    {  
                                         step3Col = j;  
                                         spiralMatrix[step3Row][j] = ++lastValue;  
                                    }  
                                    else{  
                                         break;  
                                    }  
                               }  
                          step = ++step;  
                     }  
                     //this is the step where value assigned in Vertical incrementing decrementing positional way  
                     if(step==4)  
                     {  
                               step4Row = --step3Row;  
                               step4Col = step3Col;  
                               for(int i=step4Row;i>=0;i--)  
                               {  
                                    if(spiralMatrix[i][step4Col] == 0)  
                                    {  
                                         step4Row = i;  
                                         spiralMatrix[i][step4Col] = ++lastValue;  
                                    }  
                                    else{  
                                         break;  
                                    }  
                               }  
                          step = ++step;  
                     }  
                }  
                System.out.println("Spiral Matrix is:\n");  
                for( int i=0;i<size;i++)  
                {  
                     for( int j=0;j<size;j++)  
                     {  
                          System.out.printf("%5d ",spiralMatrix[i][j]);  
                     }  
                     System.out.println("");  
                }  
           }  
           catch(Exception e)  
           {  
                e.printStackTrace();  
                System.out.println("Something Went wrong............Please run again.....");  
           }  
      }  
 }