Spring Security Login Esempio

Cosa è Spring Security?

Spring Security è un framework per  la sicurezza delle applicazioni web.

Database

File di creazione della base dati in base al tipo di database

  • Oracle

CREATE DATABASE prova<br>-- Create table<br>create table USERS<br>(<br>USERNAME VARCHAR2(36) not null,<br>PASSWORD VARCHAR2(36) not null,<br>ROLE VARCHAR2(36) not null,<br>PRIMARY KEY(USERNAME)<br>) ;</p>
<p>insert into users (USERNAME, PASSWORD, ROLE)<br>values ('dbuser1', '12345', 'ROLL_USER');</p>
<p>insert into users (USERNAME, PASSWORD, ROLE)<br>values ('dbadmin1', '12345', 'ROLL_ADMIN');</p>
<p>Commit;

  • MySql

CREATE DATABASE prova;<br>-- Create table<br>create table USERS<br>(<br>USERNAME VARCHAR(36) not null,<br>PASSWORD VARCHAR(36) not null,<br>ROLE VARCHAR(36) not null,<br>PRIMARY KEY(USERNAME)<br>) ;</p>
<p>insert into users (USERNAME, PASSWORD, ROLE)<br>values ('dbuser1', '12345', 'ROLL_USER');</p>
<p>insert into users (USERNAME, PASSWORD, ROLE)<br>values ('dbadmin1', '12345', 'ROLL_ADMIN');

  • SqlServer

CREATE DATABASE prova;<br>-- Create table<br>create table USERS<br>(<br>USERNAME VARCHAR(36) not null,<br>PASSWORD VARCHAR(36) not null,<br>ROLE VARCHAR(36) not null,<br>PRIMARY KEY(USERNAME)<br>) ;</p>
<p>insert into users (USERNAME, PASSWORD, ROLE)<br>values ('dbuser1', '12345', 'ROLL_USER');</p>
<p>insert into users (USERNAME, PASSWORD, ROLE)<br>values ('dbadmin1', '12345', 'ROLL_ADMIN');

Creazione Progetto

Dal meù File/New/Other  cliccare su “Maven Project


Selezionare  “Create a simple project (skip archetype selection)

Inserire i seguenti valori:
Group ID: iljavarolo
Artifact ID: SpringMVCSecurityXML
Packaging: war

Cliccare su “Finish

Il progetto creato dovrebbe avere una struttura del genere:

Se non esiste la cartella WEB-INF crearla.

Configurazione Spring

il progetto completo avrà il seguente aspetto

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>iljavarolo</groupId>
  <artifactId>SpringMVCSecurityXML</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  
     <properties>
        <!-- Generic properties -->
        <java.version>1.7</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
 
 
    <repositories>
        <!-- Repository for ORACLE JDBC Driver -->
        <repository>
            <id>codelds</id>
            <url>https://code.lds.org/nexus/content/groups/main-repo</url>
        </repository>
    </repositories>
 
    <dependencies>
 
        <!-- Spring framework START -->
        <!-- http://mvnrepository.com/artifact/org.springframework/spring-core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.1.4.RELEASE</version>
        </dependency>
 
        <!-- http://mvnrepository.com/artifact/org.springframework/spring-web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.1.4.RELEASE</version>
        </dependency>
 
        <!-- http://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.1.4.RELEASE</version>
        </dependency>
         
         
 
        <!-- http://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.1.4.RELEASE</version>
        </dependency>
 
         
        <!-- Spring framework END -->
 
 
        <!-- Spring Security Artifacts - START -->
        <!-- http://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
 
        <!-- http://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>3.2.5.RELEASE</version>
        </dependency>
        <!-- Spring Security Artifacts - END -->
 
        <!-- Jstl for jsp page -->
        <!-- http://mvnrepository.com/artifact/javax.servlet/jstl -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
 
        <!-- Servlet API -->
        <!-- http://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
 
        <!-- JSP API -->
        <!-- http://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
            <scope>provided</scope>
        </dependency>
 
        <!-- MySQL JDBC driver -->
        <!-- http://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.34</version>
        </dependency>
 
		<dependency>
			<groupId>com.oracle</groupId>
			<artifactId>ojdbc6</artifactId>
			<version>11.2.0</version>
		</dependency>
 
        <!-- SQLServer JDBC driver (JTDS) -->
        <!-- http://mvnrepository.com/artifact/net.sourceforge.jtds/jtds -->
        <dependency>
            <groupId>net.sourceforge.jtds</groupId>
            <artifactId>jtds</artifactId>
            <version>1.3.1</version>
        </dependency>
         
         
    </dependencies>
     
    <build>
        <finalName>SpringMVCSecurityXML</finalName>
        <plugins>
         
            <!-- Config: Maven Tomcat Plugin -->
            <!-- http://mvnrepository.com/artifact/org.apache.tomcat.maven/tomcat7-maven-plugin -->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <!-- Config: contextPath and Port (Default: /SpringMVCSecurityXML : 8080) -->
                <!--
                <configuration>
                    <path>/</path>
                    <port>8899</port>
                </configuration>
                -->   
            </plugin>
        </plugins>
    </build>        
     
     
</project>

da notare che nel web.xml si definiscono i due file di configurazione di Spring

  •          /WEB-INF/spring-security.xml
  •          /WEB-INF/data-source-cfg.xml

Inoltre, la DispatcherServlet di Spring leggerà il suo file di configurazione in base al principio {servlet-name} ==> /WEB-INF/{servlet-name}-servlet.xml, quindi in questo caso la servlet name vale “spring-mvc”   e il file avrà il nome di “spring-mvc-servlet.xml

mvc-dispatcher-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-4.1.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.1.xsd">
 
   <context:component-scan base-package="com.iljavarolo" />
   <context:annotation-config />
 
   <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>

data-source-cfg.xml per MySQL

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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-4.1.xsd">
  
  
  <bean id="myDataSource"
       class="org.springframework.jdbc.datasource.DriverManagerDataSource">
 
      <property name="driverClassName" value="com.mysql.jdbc.Driver" />
      <property name="url" value="jdbc:mysql://localhost:3306/prova" />
      <property name="username" value="root" />
      <property name="password" value="1234" />
   </bean>
     
     
</beans>

spring-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
   xsi:schemaLocation="http://www.springframework.org/schema/security
     http://www.springframework.org/schema/security/spring-security-3.2.xsd
     http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
 
    
   <http use-expressions="true">
       <intercept-url pattern="/" access="isAnonymous()" />
       <intercept-url pattern="/welcome" access="isAnonymous()" />
       <intercept-url pattern="/login" access="isAnonymous()" />
       <intercept-url pattern="/logout" access="isAnonymous()" />
 
 
       <intercept-url pattern="/userInfo"
           access="hasAnyRole('ROLE_USER', 'ROLE_ADMIN')" />
       <intercept-url pattern="/admin" access="hasRole('ROLE_ADMIN')" />
       <intercept-url pattern="/other/**" access="isAuthenticated()" />
 
       <access-denied-handler error-page="/403" />
 
       <form-login login-page='/login' login-processing-url="/j_spring_security_check"
           default-target-url="/userInfo" always-use-default-target="false"
           authentication-failure-url="/login?error=true" username-parameter="username"
           password-parameter="password" />
 
       <logout logout-url="/logout" logout-success-url="/logoutSuccessful"
           delete-cookies="JSESSIONID" invalidate-session="true" />
 
   </http>
 
   <authentication-manager>
       <authentication-provider>
           <user-service>
               <user name="user1" password="12345" authorities="ROLE_USER" />
               <user name="admin1" password="12345" authorities="ROLE_USER, ROLE_ADMIN" />
           </user-service>
       </authentication-provider>
 
 
 
       <!-- authentication from database -->
       <authentication-provider>
           <jdbc-user-service data-source-ref="myDataSource"
               users-by-username-query="select username,password, enabled from users where username=?"
               authorities-by-username-query="select username, role from users where username=?" />
       </authentication-provider>
 
   </authentication-manager>
 
</beans:beans>

Da notare  che in questo file:

  1.  E’ dichiarata una pagina per l’accesso negato con:
    <access-denied-handler error-page=”/403″ />
  2.  Per ogni Url si definisce quale ruolo puo accedere:
    <intercept-url pattern=”/admin” access=”hasRole(‘ROLE_ADMIN’)” />
    in questo caso l’url /admin può essere visualizzato solo dal ruolo ROLE_ADMIN
  3. Sono dichiarati i dettagli della login page. In particolare:
    <form-login login-page=’/login’ login-processing-url=”/j_spring_security_check”
    default-target-url=”/userInfo” always-use-default-target=”false”
    authentication-failure-url=”/login?error=true” username-parameter=”username”
    password-parameter=”password” />
    login-page=”/login” – La pagina di login da visualizzare
    authentication-failure-url=”/login?error” – Se l’autenticazione fallisce, si viene reindirizzati sulla pagina /login?error
    login-processing-url=”/j_spring_security_check”: Specifica l’url a cui il login form (che conterrà ovviamente le credenziali user e password)sarà submittato.
    Se si omette o si valorizza con “/j_spring_security_check“, il login form sarà inoltrato al controller di default di Spring.
    j_username = la username corretta
    j_password = la password corretta
    default-target-url = “/userInfo”= landing page in caso di successo
    Da notare che i valori messi in login-processing-url, j_username e j_password dovranno essere specificati anche nel form della jsp con quell id
    ossia esempio     
</li>
</ol>
<form action="j_spring_security_check" method="POST" name="f">
<table>
<tbody>
<tr>
<td>User:</td>
<td><input name="username" type="text" value="" /></td>
</tr>
<tr>
<td>Password:</td>
<td><input name="password" type="password" /></td>
</tr>
<tr>
<td><input name="submit" type="submit" value="submit" /></td>
</tr>
</tbody>
</table>
</form>
  •  Nel tag <user-service> si definiscono i vari utenti con i loro ruoli:                                 <user name=”admin1″ password=”12345″ authorities=”ROLE_USER, ROLE_ADMIN” />
  • Nel tag intercept-url si definisce, per ogni ruolo, quali risorse può  vedere. Per esempio: <intercept-url pattern=”/userInfo”access=”hasAnyRole(‘ROLE_USER’, ‘ROLE_ADMIN’)” />in questo caso l url /userInfo puo essere vista da questi ruoli ‘ROLE_USER’, ‘ROLE_ADMIN’
  •  Si indica la query da fare per controllare se le credenziali sono corrette:                 <authentication-provider><jdbc-user-service data-source-ref=”myDataSource” users-by-username-query=”select username,password, enabled from users where username=?” authorities-by-username-query=”select username, role from users where username=?” /></authentication-provider>

Gli elementi sono self-documenting. Basta passare il mouse su qualsiasi tag e si vedrà una breve descrizione.

Views

403Page.jsp

<%@page session="false"%>
<html>
<head>
<title>${title}</title>
</head>
<body>
   <h2>${message}</h2>
</body>
</html>

adminPage.jsp

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@page session="true"%>
 
<html>
<head><title>${title}</title></head>
<body>
   <h2>Message : ${message}</h2>
 
   <c:if test="${pageContext.request.userPrincipal.name != null}">
      <h3>Welcome : ${pageContext.request.userPrincipal.name}
          | <a href="<c:url value="/logout" />" >Logout</a></h3>  
   </c:if>  
</body>
</html>

loginPage.jsp

<html>
<head><title>Login</title></head>
<body>
 <h1>Login</h1>
 <form name='f' action="j_spring_security_check" method='POST'>
    <table>
       <tr>
          <td>User:</td>
          <td><input type='text' name='username' value=''></td>
       </tr>
       <tr>
          <td>Password:</td>
          <td><input type='password' name='password' /></td>
       </tr>
       <tr>
          <td><input name="submit" type="submit" value="submit" /></td>
       </tr>
    </table>
</form>
</body>
</html>

logoutSuccessfulPage.jsp

<html>
<head><title>Logout</title></head>
<body>
  <h1>Logout Successful!</h1>
</body>
</html>

userInfoPage.jsp

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@page session="true"%>
 
<html>
<head><title>${title}</title></head>
<body>
   <h2>Message : ${message}</h2>
 
   <c:if test="${pageContext.request.userPrincipal.name != null}">
      <h3>User Info : ${pageContext.request.userPrincipal.name}
          | <a href="<c:url value="/logout" />" >Logout</a></h3>  
   </c:if>  
</body>
</html>

welcomePage.jsp

<%@page session="false"%>
<html>
<head>
<title>${title}</title>
</head>
<body>
   <h1>Message : ${message}</h1>
</body>
</html>

Classi Java

In questo controller si effettuano i mapping delle richieste.
Esempio
@RequestMapping(value = “/admin”, method = RequestMethod.GET)
public String adminPage(Model model) {
model.addAttribute(“title”, “Admin”);
model.addAttribute(“message”, “Admin Page – This is protected page!”);
return “adminPage“;
}
Quando arriverà la request /admin verrà chiamato il metodo adminPage e la string di ritorno “adminPage” costituisce il nome della jsp da richiamare.

MainController.java

package com.iljavarolo.springmvcsecurity.controller;


import java.security.Principal;
 
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
@Controller
public class MainController {
 
   @RequestMapping(value = { "/", "/welcome" }, method = RequestMethod.GET)
   public String welcomePage(Model model) {
       model.addAttribute("title", "Welcome");
       model.addAttribute("message", "This is welcome page!");
       return "welcomePage";
   }
 
   @RequestMapping(value = "/admin", method = RequestMethod.GET)
   public String adminPage(Model model) {
       model.addAttribute("title", "Admin");
       model.addAttribute("message", "Admin Page - This is protected page!");
       return "adminPage";
   }
 
   @RequestMapping(value = "/login", method = RequestMethod.GET)
   public String loginPage(Model model) {
       model.addAttribute("title", "Login");
       model.addAttribute("message", "Enter your username/password:");
       return "loginPage";
   }
 
   @RequestMapping(value = "/logoutSuccessful", method = RequestMethod.GET)
   public String logoutSuccessfulPage(Model model) {
       model.addAttribute("title", "Logout");
       return "logoutSuccessfulPage";
   }
 
   @RequestMapping(value = "/userInfo", method = RequestMethod.GET)
   public String loginPage(Model model, Principal principal) {
       model.addAttribute("title", "User Info");
 
       // Sau khi user login thanh cong se co principal
       String userName = principal.getName();
 
       model.addAttribute("message",
               "User Info - This is protected page!. Hello " + userName);
 
       return "userInfoPage";
   }
 
   @RequestMapping(value = "/403", method = RequestMethod.GET)
   public String accessDenied(Model model, Principal principal) {
       model.addAttribute("title", "Access Denied!");
 
       if (principal != null) {
           model.addAttribute("message", "Hi " + principal.getName()
                   + "<br> You do not have permission to access this page!");
       } else {
           model.addAttribute("msg",
                   "You do not have permission to access this page!");
       }
       return "403Page";
   }
}

Build  Applicazione

Buildare l’intero progetto, cliccando su run As–>Maven Install

Dal menù “Run Configuration” settare la seguente configurazione per l’avvio:

inserire i seguenti valori:
Name: Run SpringMVCSecurityXML
Base directory: ${workspace_loc:/SpringMVCSecurityXML}
Goals: tomcat7:run

Buildare l’intero progetto cliccando su “Run“:

Avvio Applicazione

digitare nel browser questa url:

http://localhost:8080/SpringMVCSecurityXML/userInfo

Se i dati inseriti sono errati, si verra reindirizzato sempre sulla stessa pagina di login.

Inserendo invece le credenziali corrette:

Se si digita questa URL

http://localhost:8080/SpringMVCSecurityXML/admin

si ottiene:

Questo perchè questa risorsa è permessa solo per l’ ADMIN (ROLE-ADMIN).

Se si fa il logout e si ritorna sull’ url su citato si verrà reindirizzati nella normale pagina di login

Download Sorgenti Intero Progetto

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *