Spring MVC + Spring Security + Remember Me + Hibernate + Maven …

Saludos,

En esta nueva entrada haremos uso de spring mvc para crear un CRUD que permita registrar información del cliente que tendrá autorización a nuestra Rest API que hemos ido desarrollando. Como pudieron leer en esa entrada después de mucho investigar encontramos que es posible registrar datos del cliente que puede acceder a los recursos expuestos en nuestra API tales como el ClientId, ClientSecret, Athorities entre otros en una tabla de nuestra base de datos, bueno para esta entrada les ilustraré como hice un pequeño ejemplo que nos permitirá registrar nuestro cliente y generar un clientSecret, al estilo google, facebook cuando hacemos uso se sus servidores de autenticción OAUTH2, claro está guardando las proporciones.

Y como siempre agradecer a toda la gente que expone sus conocimientos en la web para que los demás podamos crecer técnicamente, agradecimiento especial a la persona de este blog que lo he encontrado muy útil en mi estudio del mundo de spring framework.

Bueno ahora si a lo que vinimos.

1.- Frameworks

  • Maven
  • Spring Framework – 4.3.3.RELEASE
  • Spring Security – 4.0.1.RELEASE
  • Hibernate – 5.1.2.Final
  • slf4j – 1.7.6
  • log4j – 1.2.17
  • Oracje JDBC – 11.2.0, como saben este driver es propietario por ende no se encuentra en los repos de maven, para su instalación pueden guiarse de acá (Install Oracle JDBC maven)
  • Java JDK 1.7.0_72

2.- Servidor de Aplicaciones y base de datos

  • Apache Tomcat v8.0
  • Oracle XE 11g 64 Bits

3.- IDE

  • Eclipse Luna Service Release 2 (4.4.2)
  • Oracle Sql Developer 4.0.3.16

4.- Equipo de desarrollo

  • HP ProBook
  • Procesador: Intel Core i5 2.5 GHZ
  • Memoria Ram: 8 GB
  • SO: Windows 7 64 Bits

5.- Otros

  • Mozilla Firefox 43.0.4
  • FireFox Add On -> RestClient

6.- Estructura del proyecto

mvc_1

7.- Archivo POM(Project Object Model) – Maven


<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/maven-v4_0_0.xsd">

           <modelVersion>4.0.0</modelVersion>
           <groupId>co.com.microservice</groupId>
           <artifactId>registration</artifactId>
           <packaging>war</packaging>
           <version>0.0.1-SNAPSHOT</version>
           <name>registration Maven Webapp</name>
           <url>http://maven.apache.org</url>

           <developers>
                 <developer>
                      <id>wortiz</id>
                      <name>Wilman Ortiz</name>
                      <email>-</email>
                      <url>https://willmanortiz.wordpress.com/</url>
                      <roles>
                           <role>developer</role>
                       </roles>
                 </developer>
           </developers>

           <licenses>
                 <license>
                      <name>GPL 3</name>
                      <url>http://www.gnu.org/licenses/gpl-3.0.html</url>
                 </license>
           </licenses>

           <properties>
                  <springframework.version>4.3.3.RELEASE</springframework.version>
                  <springsecurity.version>4.0.1.RELEASE</springsecurity.version>
                  <hibernate.version>5.1.2.Final</hibernate.version>
                  <slf4j.version>1.7.6</slf4j.version>
                  <log4j.version>1.2.17</log4j.version>
                  <oracle.version>11.2.0</oracle.version>
                  <aspectj.version>1.7.4</aspectj.version>
                  <jackson.version>2.8.3</jackson.version>
                  <junit.version>4.12</junit.version>
                  <servlet.version>3.1.0</servlet.version>
                  <jsp.version>2.3.1</jsp.version>
                  <jstl.version>1.2</jstl.version>
           </properties>

           <dependencies>

                    <!-- Spring -->
                    <dependency>
                          <groupId>org.springframework</groupId>
                          <artifactId>spring-core</artifactId>
                          <version>${springframework.version}</version>
                    </dependency>
                    <dependency>
                          <groupId>org.springframework</groupId>
                          <artifactId>spring-web</artifactId>
                          <version>${springframework.version}</version>
                    </dependency>
                    <dependency>
                          <groupId>org.springframework</groupId>
                          <artifactId>spring-webmvc</artifactId>
                          <version>${springframework.version}</version>
                    </dependency>
                    <dependency>
                           <groupId>org.springframework</groupId>
                           <artifactId>spring-tx</artifactId>
                           <version>${springframework.version}</version>
                    </dependency>
                    <dependency>
                           <groupId>org.springframework</groupId>
                           <artifactId>spring-orm</artifactId>
                           <version>${springframework.version}</version>
                    </dependency>

                    <!-- Spring Security -->
                    <dependency>
                           <groupId>org.springframework.security</groupId>
                           <artifactId>spring-security-web</artifactId>
                           <version>${springsecurity.version}</version>
                    </dependency>
                    <dependency>
                           <groupId>org.springframework.security</groupId>
                           <artifactId>spring-security-config</artifactId>
                           <version>${springsecurity.version}</version>
                    </dependency>
                    <dependency>
                           <groupId>org.springframework.security</groupId>
                           <artifactId>spring-security-taglibs</artifactId>
                           <version>${springsecurity.version}</version>
                    </dependency>
                
                   <!-- Spring AOP + AspectJ -->
                   <dependency>
                           <groupId>org.springframework</groupId>
                           <artifactId>spring-aop</artifactId>
                           <version>${springframework.version}</version>
                   </dependency>

                   <dependency>
                           <groupId>org.aspectj</groupId>
                           <artifactId>aspectjrt</artifactId>
                           <version>${aspectj.version}</version>
                           <scope>runtime</scope>
                   </dependency>

                   <dependency>
                           <groupId>org.aspectj</groupId>
                           <artifactId>aspectjweaver</artifactId>
                           <version>${aspectj.version}</version>
                   </dependency>

                   <!-- Hibernate -->
                   <dependency>
                          <groupId>org.hibernate</groupId>
                          <artifactId>hibernate-core</artifactId>
                          <version>${hibernate.version}</version>
                   </dependency>

                   <!-- jsr303 validation -->
                   <dependency>
                          <groupId>javax.validation</groupId>
                          <artifactId>validation-api</artifactId>
                          <version>1.1.0.Final</version>
                   </dependency>
                   <dependency>
                           <groupId>org.hibernate</groupId>
                           <artifactId>hibernate-validator</artifactId>
                           <version>5.1.3.Final</version>
                   </dependency>

                   <!-- Logger -->
                   <dependency>
                           <groupId>log4j</groupId>
                           <artifactId>log4j</artifactId>
                           <version>${log4j.version}</version>
                   </dependency>

                   <dependency>
                            <groupId>org.slf4j</groupId>
                            <artifactId>slf4j-log4j12</artifactId>
                            <version>${slf4j.version}</version>
                   </dependency>

                   <dependency>
                            <groupId>org.slf4j</groupId>
                            <artifactId>slf4j-api</artifactId>
                            <version>${slf4j.version}</version>
                   </dependency>

                   <!-- Oracle database driver -->
                   <dependency>
                            <groupId>com.oracle</groupId>
                            <artifactId>ojdbc6</artifactId>
                            <version>${oracle.version}</version>
                   </dependency>

                   <!-- JUnit -->
                   <dependency>
                           <groupId>junit</groupId>
                           <artifactId>junit</artifactId>
                           <version>${junit.version}</version>
                           <scope>test</scope>
                   </dependency>

                   <!-- Servlet -->
                   <dependency>
                        <groupId>javax.servlet</groupId>
                        <artifactId>javax.servlet-api</artifactId>
                        <version>${servlet.version}</version>
                   </dependency>
                   <dependency>
                          <groupId>javax.servlet.jsp</groupId>
                          <artifactId>javax.servlet.jsp-api</artifactId>
                          <version>${jsp.version}</version>
                   </dependency>
                   <dependency>
                          <groupId>javax.servlet</groupId>
                          <artifactId>jstl</artifactId>
                          <version>${jstl.version}</version>
                   </dependency>

                   <!-- Jackson -->
                   <dependency>
                          <groupId>com.fasterxml.jackson.core</groupId>
                          <artifactId>jackson-annotations</artifactId>
                          <version>${jackson.version}</version>
                   </dependency>
                   <dependency>
                          <groupId>com.fasterxml.jackson.core</groupId>
                          <artifactId>jackson-databind</artifactId>
                          <version>${jackson.version}</version>
                   </dependency>

           </dependencies>
           <build>
                <finalName>registration</finalName>
                <plugins>
                        <plugin>
                              <groupId>org.apache.maven.plugins</groupId>
                              <artifactId>maven-war-plugin</artifactId>
                              <version>2.4</version>
                              <configuration>
                                       <warSourceDirectory>src/main/webapp</warSourceDirectory>
                                       <warName>registration</warName>
                                       <failOnMissingWebXml>false</failOnMissingWebXml>
                              </configuration>
                        </plugin>
                        <plugin>
                              <artifactId>maven-compiler-plugin</artifactId>
                              <version>3.3</version>
                              <configuration>
                                       <source>1.7</source>
                                       <target>1.7</target>
                              </configuration>
                        </plugin>
                </plugins>
           </build>
</project>

8.- Modelo
8.1.- User.java

package co.com.registration.application.model;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@Entity
@Table(name = "USERS", catalog = "", schema = "APPLICATION")
@NamedQueries({
    @NamedQuery(name = "User.findAll"                   , query = "SELECT u FROM User u"),
    @NamedQuery(name = "User.findByIdUser"              , query = "SELECT u FROM User u WHERE u.idUser = :idUser"),
    @NamedQuery(name = "User.findByCedula"              , query = "SELECT u FROM User u WHERE u.cedula = :cedula"),
    @NamedQuery(name = "User.findByNombre"              , query = "SELECT u FROM User u WHERE u.nombre = :nombre"),
    @NamedQuery(name = "User.findByApellido"            , query = "SELECT u FROM User u WHERE u.apellido = :apellido"),
    @NamedQuery(name = "User.findByDireccion"           , query = "SELECT u FROM User u WHERE u.direccion = :direccion"),
    @NamedQuery(name = "User.findByFechaNacimiento"     , query = "SELECT u FROM User u WHERE u.fechaNacimiento = :fechaNacimiento"),
    @NamedQuery(name = "User.findByFechaIngreso"        , query = "SELECT u FROM User u WHERE u.fechaIngreso = :fechaIngreso"),
    @NamedQuery(name = "User.findByFechaRetiro"         , query = "SELECT u FROM User u WHERE u.fechaRetiro = :fechaRetiro"),
    @NamedQuery(name = "User.findByTelefono"            , query = "SELECT u FROM User u WHERE u.telefono = :telefono"),
    @NamedQuery(name = "User.findByEmail"               , query = "SELECT u FROM User u WHERE u.email = :email"),
    @NamedQuery(name = "User.findByLogin"               , query = "SELECT u FROM User u WHERE u.login = :login"),
    @NamedQuery(name = "User.findByPassword"            , query = "SELECT u FROM User u WHERE u.password = :password"),
    @NamedQuery(name = "User.findByEnable"              , query = "SELECT u FROM User u WHERE u.enable = :enable"),
    @NamedQuery(name = "User.findByAccountNonExpired"   , query = "SELECT u FROM User u WHERE u.accountNonExpired = :accountNonExpired"),
    @NamedQuery(name = "User.findByCredentialNonExpired", query = "SELECT u FROM User u WHERE u.credentialNonExpired = :credentialNonExpired"),
    @NamedQuery(name = "User.findByAccountNonLocked"    , query = "SELECT u FROM User u WHERE u.accountNonLocked = :accountNonLocked")})
public class User implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    // @Max(value=?)  @Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
    @Id
    @Basic(optional = false)
    @NotNull
    @Column(name = "ID_USER")
    @SequenceGenerator(name = "sec_user", sequenceName = "SQ_USERS", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="sec_user")
    private BigDecimal idUser;
    
    @Basic(optional = false)
    @NotNull
    @Column(name = "CEDULA")
    private BigInteger cedula;
    
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 50)
    @Column(name = "NOMBRE")
    private String nombre;
    
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 50)
    @Column(name = "APELLIDO")
    private String apellido;
    
    @Size(max = 100)
    @Column(name = "DIRECCION")
    private String direccion;
    
    @Column(name = "FECHA_NACIMIENTO")
    @Temporal(TemporalType.TIMESTAMP)
    private Date fechaNacimiento;
    
    @Column(name = "FECHA_INGRESO")
    @Temporal(TemporalType.TIMESTAMP)
    private Date fechaIngreso;
    
    @Column(name = "FECHA_RETIRO")
    @Temporal(TemporalType.TIMESTAMP)
    private Date fechaRetiro;
    
    @Size(max = 30)
    @Column(name = "TELEFONO")
    private String telefono;
    
    // @Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message="Invalid email")//if the field contains email address consider using this annotation to enforce field validation
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 100)
    @Column(name = "EMAIL")
    private String email;
    
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 30)
    @Column(name = "LOGIN")
    private String login;
    
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 100)
    @Column(name = "PASSWORD")
    private String password;
    
    @Size(max = 10)
    @Column(name = "ENABLE")
    private String enable;
    
    @Size(max = 10)
    @Column(name = "ACCOUNT_NON_EXPIRED")
    private String accountNonExpired;
    
    @Size(max = 10)
    @Column(name = "CREDENTIAL_NON_EXPIRED")
    private String credentialNonExpired;
    
    @Size(max = 10)
    @Column(name = "ACCOUNT_NON_LOCKED")
    private String accountNonLocked;
    
    @ManyToMany(mappedBy = "userList", fetch = FetchType.LAZY)
    private List<Role> roleList;
    
    public User() {
    }

    public User(BigDecimal idUser) {
        this.idUser = idUser;
    }

    public User(BigDecimal idUser, BigInteger cedula, String nombre, String apellido, String email, String login, String password) {
        this.idUser = idUser;
        this.cedula = cedula;
        this.nombre = nombre;
        this.apellido = apellido;
        this.email = email;
        this.login = login;
        this.password = password;
    }

    public BigDecimal getIdUser() {
        return idUser;
    }

    public void setIdUser(BigDecimal idUser) {
        this.idUser = idUser;
    }

    public BigInteger getCedula() {
        return cedula;
    }

    public void setCedula(BigInteger cedula) {
        this.cedula = cedula;
    }

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public String getApellido() {
        return apellido;
    }

    public void setApellido(String apellido) {
        this.apellido = apellido;
    }

    public String getDireccion() {
        return direccion;
    }

    public void setDireccion(String direccion) {
        this.direccion = direccion;
    }

    public Date getFechaNacimiento() {
        return fechaNacimiento;
    }

    public void setFechaNacimiento(Date fechaNacimiento) {
        this.fechaNacimiento = fechaNacimiento;
    }

    public Date getFechaIngreso() {
        return fechaIngreso;
    }

    public void setFechaIngreso(Date fechaIngreso) {
        this.fechaIngreso = fechaIngreso;
    }

    public Date getFechaRetiro() {
        return fechaRetiro;
    }

    public void setFechaRetiro(Date fechaRetiro) {
        this.fechaRetiro = fechaRetiro;
    }

    public String getTelefono() {
        return telefono;
    }

    public void setTelefono(String telefono) {
        this.telefono = telefono;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEnable() {
        return enable;
    }

    public void setEnable(String enable) {
        this.enable = enable;
    }

    public String getAccountNonExpired() {
        return accountNonExpired;
    }

    public void setAccountNonExpired(String accountNonExpired) {
        this.accountNonExpired = accountNonExpired;
    }

    public String getCredentialNonExpired() {
        return credentialNonExpired;
    }

    public void setCredentialNonExpired(String credentialNonExpired) {
        this.credentialNonExpired = credentialNonExpired;
    }

    public String getAccountNonLocked() {
        return accountNonLocked;
    }

    public void setAccountNonLocked(String accountNonLocked) {
        this.accountNonLocked = accountNonLocked;
    }

    public List<Role> getRoleList() {
        return roleList;
    }

    public void setRoleList(List<Role> roleList) {
        this.roleList = roleList;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (idUser != null ? idUser.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof User)) {
            return false;
        }
        User other = (User) object;
        if ((this.idUser == null && other.idUser != null) || (this.idUser != null && !this.idUser.equals(other.idUser))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "modelo.User[ idUser=" + idUser + " ]";
    }
    
}

8.1.- Role.java

package co.com.registration.application.model;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@Entity
@Table(name = "ROLES", catalog = "", schema = "APPLICATION")
@NamedQueries({
    @NamedQuery(name = "Role.findAll"     , query = "SELECT r FROM Role r"),
    @NamedQuery(name = "Role.findByIdRole", query = "SELECT r FROM Role r WHERE r.idRole = :idRole"),
    @NamedQuery(name = "Role.findByRole"  , query = "SELECT r FROM Role r WHERE r.role = :role")})
public class Role implements Serializable {
   
    private static final long serialVersionUID = 1L;
    
    // @Max(value=?)  @Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
    @Id
    @Basic(optional = false)
    @NotNull
    @Column(name = "ID_ROLE")
    @SequenceGenerator(name = "sec_roles", sequenceName = "SQ_ROLES", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="sec_roles")
    private BigDecimal idRole;
    
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 50)
    @Column(name = "ROLE")
    private String role;
    
    @JoinTable(name = "USERS_ROLES", joinColumns = {
        @JoinColumn(name = "ROLE_ID", referencedColumnName = "ID_ROLE")}, inverseJoinColumns = {
        @JoinColumn(name = "USER_ID", referencedColumnName = "ID_USER")})
    @ManyToMany(fetch = FetchType.LAZY)
    private List<User> userList;

    public Role() {
    }

    public Role(BigDecimal idRole) {
        this.idRole = idRole;
    }

    public Role(BigDecimal idRole, String role) {
        this.idRole = idRole;
        this.role = role;
    }

    public BigDecimal getIdRole() {
        return idRole;
    }

    public void setIdRole(BigDecimal idRole) {
        this.idRole = idRole;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }

    public List<User> getUserList() {
        return userList;
    }

    public void setUserList(List<User> userList) {
        this.userList = userList;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (idRole != null ? idRole.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof Role)) {
            return false;
        }
        Role other = (Role) object;
        if ((this.idRole == null && other.idRole != null) || (this.idRole != null && !this.idRole.equals(other.idRole))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "modelo.Role[ idRole=" + idRole + " ]";
    }
    
}

8.3.- PersistentLogins.java

package co.com.registration.application.model;

import java.io.Serializable;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@Entity
@Table(name = "PERSISTENT_LOGINS", catalog = "", schema = "APPLICATION")
@NamedQueries({
    @NamedQuery(name = "PersistentLogins.findAll", query = "SELECT p FROM PersistentLogins p"),
    @NamedQuery(name = "PersistentLogins.findByUsername", query = "SELECT p FROM PersistentLogins p WHERE p.username = :username"),
    @NamedQuery(name = "PersistentLogins.findBySeries", query = "SELECT p FROM PersistentLogins p WHERE p.series = :series"),
    @NamedQuery(name = "PersistentLogins.findByToken", query = "SELECT p FROM PersistentLogins p WHERE p.token = :token"),
    @NamedQuery(name = "PersistentLogins.findByLastUsed", query = "SELECT p FROM PersistentLogins p WHERE p.lastUsed = :lastUsed")})
public class PersistentLogins implements Serializable {
	
    private static final long serialVersionUID = 1L;
    
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 64)
    @Column(name = "USERNAME", nullable = false, length = 64)
    private String username;
    
    @Id
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 64)
    @Column(name = "SERIES", nullable = false, length = 64)
    private String series;
    
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 64)
    @Column(name = "TOKEN", nullable = false, length = 64)
    private String token;
    
    @Basic(optional = false)
    @NotNull
    @Column(name = "LAST_USED", nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date lastUsed;

    public PersistentLogins() {
    }

    public PersistentLogins(String series) {
        this.series = series;
    }

    public PersistentLogins(String series, String username, String token, Date lastUsed) {
        this.series = series;
        this.username = username;
        this.token = token;
        this.lastUsed = lastUsed;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getSeries() {
        return series;
    }

    public void setSeries(String series) {
        this.series = series;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public Date getLastUsed() {
        return lastUsed;
    }

    public void setLastUsed(Date lastUsed) {
        this.lastUsed = lastUsed;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (series != null ? series.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof PersistentLogins)) {
            return false;
        }
        PersistentLogins other = (PersistentLogins) object;
        if ((this.series == null && other.series != null) || (this.series != null && !this.series.equals(other.series))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "modelo.PersistentLogins[ series=" + series + " ]";
    }
    
}

8.4.- OauthClientDetails.java

package co.com.registration.application.model;

import java.io.Serializable;
import java.math.BigDecimal;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.hibernate.annotations.Proxy;

@Entity
@Table(name = "OAUTH_CLIENT_DETAILS", catalog = "", schema = "APPLICATION", uniqueConstraints = {
    @UniqueConstraint(columnNames = {"CLIENT_ID"})})
@Proxy(lazy=false)
@NamedQueries({
    @NamedQuery(name = "OauthClientDetails.findAll", query = "SELECT o FROM OauthClientDetails o"),
    @NamedQuery(name = "OauthClientDetails.findByOid", query = "SELECT o FROM OauthClientDetails o WHERE o.oid = :oid"),
    @NamedQuery(name = "OauthClientDetails.findByClientId", query = "SELECT o FROM OauthClientDetails o WHERE o.clientId = :clientId"),
    @NamedQuery(name = "OauthClientDetails.findByClientName", query = "SELECT o FROM OauthClientDetails o WHERE o.clientName = :clientName"),
    @NamedQuery(name = "OauthClientDetails.findByResourceIds", query = "SELECT o FROM OauthClientDetails o WHERE o.resourceIds = :resourceIds"),
    @NamedQuery(name = "OauthClientDetails.findByClientSecret", query = "SELECT o FROM OauthClientDetails o WHERE o.clientSecret = :clientSecret"),
    @NamedQuery(name = "OauthClientDetails.findByScope", query = "SELECT o FROM OauthClientDetails o WHERE o.scope = :scope"),
    @NamedQuery(name = "OauthClientDetails.findByAuthorizedGrantTypes", query = "SELECT o FROM OauthClientDetails o WHERE o.authorizedGrantTypes = :authorizedGrantTypes"),
    @NamedQuery(name = "OauthClientDetails.findByWebServerRedirectUri", query = "SELECT o FROM OauthClientDetails o WHERE o.webServerRedirectUri = :webServerRedirectUri"),
    @NamedQuery(name = "OauthClientDetails.findByAuthorities", query = "SELECT o FROM OauthClientDetails o WHERE o.authorities = :authorities"),
    @NamedQuery(name = "OauthClientDetails.findByAccessTokenValidity", query = "SELECT o FROM OauthClientDetails o WHERE o.accessTokenValidity = :accessTokenValidity"),
    @NamedQuery(name = "OauthClientDetails.findByRefreshTokenValidity", query = "SELECT o FROM OauthClientDetails o WHERE o.refreshTokenValidity = :refreshTokenValidity"),
    @NamedQuery(name = "OauthClientDetails.findByAdditionalInformation", query = "SELECT o FROM OauthClientDetails o WHERE o.additionalInformation = :additionalInformation"),
    @NamedQuery(name = "OauthClientDetails.findByAutoapprove", query = "SELECT o FROM OauthClientDetails o WHERE o.autoapprove = :autoapprove")})
public class OauthClientDetails implements Serializable {
    private static final long serialVersionUID = 1L;
    // @Max(value=?)  @Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
    @Id
    @Basic(optional = false)
    @NotNull
    @Column(name = "OID", nullable = false, precision = 0, scale = -127)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "OAUTH_SEQ")
    @SequenceGenerator(name = "OAUTH_SEQ", sequenceName = "SQ_OAUTH", allocationSize = 1)
    private BigDecimal oid;
    @Size(max = 255)
    @Column(name = "CLIENT_ID", length = 255)
    private String clientId;
    @Size(max = 255)
    @Column(name = "CLIENT_NAME", length = 255)
    private String clientName;
    @Size(max = 255)
    @Column(name = "RESOURCE_IDS", length = 255)
    private String resourceIds;
    @Size(max = 255)
    @Column(name = "CLIENT_SECRET", length = 255)
    private String clientSecret;
    @Size(max = 255)
    @Column(name = "SCOPE", length = 255)
    private String scope;
    @Size(max = 255)
    @Column(name = "AUTHORIZED_GRANT_TYPES", length = 255)
    private String authorizedGrantTypes;
    @Size(max = 255)
    @Column(name = "WEB_SERVER_REDIRECT_URI", length = 255)
    private String webServerRedirectUri;
    @Size(max = 255)
    @Column(name = "AUTHORITIES", length = 255)
    private String authorities;
    @Column(name = "ACCESS_TOKEN_VALIDITY")
    private Long accessTokenValidity;
    @Column(name = "REFRESH_TOKEN_VALIDITY")
    private Long refreshTokenValidity;
    @Size(max = 2000)
    @Column(name = "ADDITIONAL_INFORMATION", length = 2000)
    private String additionalInformation;
    @Size(max = 255)
    @Column(name = "AUTOAPPROVE", length = 255)
    private String autoapprove;

    public OauthClientDetails() {
    }

    public OauthClientDetails(BigDecimal oid) {
        this.oid = oid;
    }

    public BigDecimal getOid() {
        return oid;
    }

    public void setOid(BigDecimal oid) {
        this.oid = oid;
    }

    public String getClientId() {
        return clientId;
    }

    public void setClientId(String clientId) {
        this.clientId = clientId;
    }

    public String getClientName() {
        return clientName;
    }

    public void setClientName(String clientName) {
        this.clientName = clientName;
    }

    public String getResourceIds() {
        return resourceIds;
    }

    public void setResourceIds(String resourceIds) {
        this.resourceIds = resourceIds;
    }

    public String getClientSecret() {
        return clientSecret;
    }

    public void setClientSecret(String clientSecret) {
        this.clientSecret = clientSecret;
    }

    public String getScope() {
        return scope;
    }

    public void setScope(String scope) {
        this.scope = scope;
    }

    public String getAuthorizedGrantTypes() {
        return authorizedGrantTypes;
    }

    public void setAuthorizedGrantTypes(String authorizedGrantTypes) {
        this.authorizedGrantTypes = authorizedGrantTypes;
    }

    public String getWebServerRedirectUri() {
        return webServerRedirectUri;
    }

    public void setWebServerRedirectUri(String webServerRedirectUri) {
        this.webServerRedirectUri = webServerRedirectUri;
    }

    public String getAuthorities() {
        return authorities;
    }

    public void setAuthorities(String authorities) {
        this.authorities = authorities;
    }

    public Long getAccessTokenValidity() {
        return accessTokenValidity;
    }

    public void setAccessTokenValidity(Long accessTokenValidity) {
        this.accessTokenValidity = accessTokenValidity;
    }

    public Long getRefreshTokenValidity() {
        return refreshTokenValidity;
    }

    public void setRefreshTokenValidity(Long refreshTokenValidity) {
        this.refreshTokenValidity = refreshTokenValidity;
    }

    public String getAdditionalInformation() {
        return additionalInformation;
    }

    public void setAdditionalInformation(String additionalInformation) {
        this.additionalInformation = additionalInformation;
    }

    public String getAutoapprove() {
        return autoapprove;
    }

    public void setAutoapprove(String autoapprove) {
        this.autoapprove = autoapprove;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (oid != null ? oid.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof OauthClientDetails)) {
            return false;
        }
        OauthClientDetails other = (OauthClientDetails) object;
        if ((this.oid == null && other.oid != null) || (this.oid != null && !this.oid.equals(other.oid))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "modelo.OauthClientDetails[ oid=" + oid + " ]";
    }
    
}

9.- GenericDAO.java

package co.com.registration.application.repository.generic;

import java.util.List;

public interface GenericDAO<T, ID extends java.io.Serializable> {
	
	public List<T> getAllRows();
	
	public T getById(ID id);
	
	public T save(T entity);
	
	public void delete(ID id);
	
	public void delete(T entity);
	
	public T update(T entity);
	
}

10.- GenericDAOImpl.java

package co.com.registration.application.repository.generic;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.hibernate.Query;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

public abstract class GenericDAOImpl<T, ID extends java.io.Serializable> implements GenericDAO<T, ID>{
	
	private Class<T> clazz;
	@Autowired
	private SessionFactory sessionFactory;
	
	public GenericDAOImpl(Class<T> persistenceClass) {
		this.clazz = persistenceClass;
	}
	
	@Override
	@Transactional(readOnly = true)
	public List<T> getAllRows() {
		StringBuilder sQuery = new StringBuilder();
		
		sQuery.append("SELECT t \n");
		sQuery.append("FROM ");
		sQuery.append(getClazz().getSimpleName());
		sQuery.append(" t");
		
		Query query = getSessionFactory().getCurrentSession().createQuery(sQuery.toString());
				
		List<T> entities = castGenerics(getClazz(), query.list());
		
		return entities;
	}

	@Override
	@Transactional(readOnly = true)
	public T getById(ID id) {
		
		Object object = getSessionFactory()
			            .getCurrentSession()
			            .get(getClazz(), id);
		
		if (getClazz().isInstance(object)){
			T entity = getClazz().cast(object); 
			return entity;
		}
		
		return null;
	}

	@Override
	@Transactional(readOnly = false)
	public T save(T entity) {
		if (entity != null){
			getSessionFactory()
		    .getCurrentSession()
		    .persist(entity);
		    return entity;
		}
		return null;
	}

	@Override
	@Transactional(readOnly = false)
	public void delete(ID id) {
		
		try{
			Object object = getSessionFactory().getCurrentSession().get(getClazz(), id);
			
			if (getClazz().isInstance(object)){
				T entity = getClazz().cast(object); 
				getSessionFactory().getCurrentSession().delete(entity);
			}			
			
		}catch (Exception e){
			e.printStackTrace();
		}
	}
	
	@Override
	@Transactional(readOnly = false)
	public void delete(T entity) {
		getSessionFactory().getCurrentSession().delete(entity);
    }

	@Override
	@Transactional(readOnly = false)
	public T update(T entity) {
		if (entity != null){
		    getSessionFactory()
		    .getCurrentSession().update(entity);;
		    return entity;
		}
		return null;
	}
	
	public static <T> List<T> castGenerics(Class<? extends T> clazz, Collection<?> collections) {
	    List<T> list = new ArrayList<T>(collections.size());
	    
	    for(Object object : collections)
	    	list.add(clazz.cast(object));
	    
	    return list;
	}
	
	public Class<T> getClazz() {
		return clazz;
	}

	public void setClazz(Class<T> clazz) {
		this.clazz = clazz;
	}

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

}

11.- UserDao.java

package co.com.registration.application.repository.dao;

import co.com.registration.application.model.User;
import co.com.registration.application.repository.generic.GenericDAO;

public interface UserDao extends GenericDAO<User, Long> {
	
	public boolean isUserAvailable(String login);
	
	public User loadUserByUsername(String username);
	
}

12.- RoleDao.java

package co.com.registration.application.repository.dao;

import java.util.List;

import co.com.registration.application.model.Role;
import co.com.registration.application.repository.generic.GenericDAO;

public interface RoleDao extends GenericDAO<Role, Long> {
	
	public List<Role> getRoleListNq();
	
}

13.- OAuthClientDAO.java

package co.com.registration.application.repository.dao;

import java.math.BigDecimal;

import co.com.registration.application.model.OauthClientDetails;
import co.com.registration.application.repository.generic.GenericDAO;

public interface OAuthClientDAO  extends GenericDAO<OauthClientDetails, String>{
	
	public boolean isClientAvailable(String clientId);
	public OauthClientDetails getByOauth2Id(BigDecimal oid);
	public OauthClientDetails loadClientByName(String clientName);
	public void eliminarById(BigDecimal oauth2Id);
	
}

15.- Implementaciones de los DAOs
15.1.- UserDaoImpl.java

package co.com.registration.application.repository.impl;

import javax.persistence.NoResultException;

import org.hibernate.Query;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import co.com.registration.application.annotation.InfoLogger;
import co.com.registration.application.model.User;
import co.com.registration.application.repository.dao.UserDao;
import co.com.registration.application.repository.generic.GenericDAOImpl;

@Repository("userDao")
@Transactional
public class UserDaoImpl extends GenericDAOImpl<User, Long> implements UserDao{

	public UserDaoImpl() {
		super(User.class);
	}

	@Override
	public boolean isUserAvailable(String login) {
		Assert.notNull(login);
		
		StringBuilder sQuery = new StringBuilder();
		
		sQuery.append("SELECT count(*) \n");
		sQuery.append("FROM ");
		sQuery.append(getClazz().getSimpleName());
		sQuery.append(" u \n");
		sQuery.append("WHERE u.login = :ipLogin");
		
		Query query = getSessionFactory().getCurrentSession().createQuery(sQuery.toString());
		query.setParameter("ipLogin", login);
		
		Long count = (Long) query.list().get(0);
		
		return count < 1; } @Override @InfoLogger(source = "loadUserByUsername") public User loadUserByUsername(String username) { Assert.notNull(username); User user = null; StringBuilder sQuery = new StringBuilder(); sQuery.append("SELECT u \n"); sQuery.append("FROM "); sQuery.append(getClazz().getSimpleName()); sQuery.append(" u \n"); sQuery.append("WHERE u.login = :ipLogin"); try{ user = (User) getSessionFactory() .getCurrentSession() .createQuery(sQuery.toString()) .setParameter("ipLogin", username) .list().get(0); }catch (NoResultException nre){ System.out.println("No se encontro el usuario --> " + nre.toString());
		}
		
		return user;
	}

}

15.2.- RoleDaoImpl.java

package co.com.registration.application.repository.impl;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import co.com.registration.application.model.Role;
import co.com.registration.application.repository.dao.RoleDao;
import co.com.registration.application.repository.generic.GenericDAOImpl;

@Repository("roleDao")
@Transactional
public class RoleDaoImpl extends GenericDAOImpl<Role, Long> implements RoleDao {

	public RoleDaoImpl() {
		super(Role.class);
	}

	@Override
	public List<Role> getRoleListNq() {
		
		StringBuilder sQuery = new StringBuilder();
		
		sQuery.append("SELECT r");
		sQuery.append("FROM ");
		sQuery.append(getClazz().getSimpleName());
		sQuery.append("r");
		
		Query query = getSessionFactory().getCurrentSession().createQuery(sQuery.toString()); 
		
		List<Role> roles = new ArrayList<Role>();
		
		for (Object object : query.list()){
			 if (object instanceof Role){
				 roles.add((Role)object);
			 }
		}
		
		return roles;
	}	
	
}

15.3.- RememberMeDaoImpl.java

package co.com.registration.application.repository.impl;

import java.util.Date;

import javax.persistence.Query;

import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import co.com.registration.application.model.PersistentLogins;
import co.com.registration.application.repository.generic.GenericDAOImpl;

@Repository("customPersistentTokenRepository")
@Transactional
public class RememberMeDaoImpl extends GenericDAOImpl<PersistentLogins, Long> implements PersistentTokenRepository {

	public RememberMeDaoImpl() {
		super(PersistentLogins.class);
	}

	@Override
	public void createNewToken(PersistentRememberMeToken token) {
		PersistentLogins login = new PersistentLogins();
		
		login.setUsername(token.getUsername());
		login.setSeries(token.getSeries());
		login.setToken(token.getTokenValue());
		login.setLastUsed(token.getDate());
		
		save(login);
	}

	@Override
	public void updateToken(String series, String tokenValue, Date lastUsed) {
		PersistentLogins login = new PersistentLogins();
		
		login.setSeries(series);
		login.setToken(tokenValue);
		login.setLastUsed(lastUsed);
		
		update(login);
	}

	@Override
	public PersistentRememberMeToken getTokenForSeries(String seriesId) {
		
		StringBuffer sQuery = new StringBuffer();
		
		sQuery.append("SELECT p ");
		sQuery.append("FROM ");
		sQuery.append(getClazz().getSimpleName());
		sQuery.append(" p ");
		sQuery.append("WHERE p.series = :ipSeries");
		
		List<?> login = getSessionFactory().getCurrentSession()
	                                       .createQuery(sQuery.toString())
	                                       .setParameter("ipSeries", seriesId)
	                                       .list();
		
		if (login.size() > 0){
		
			return new PersistentRememberMeToken(((PersistentRememberMeToken) login.get(0)).getUsername(),
												 ((PersistentRememberMeToken) login.get(0)).getSeries(),
												 ((PersistentLogins) login.get(0)).getToken(),
			  									 ((PersistentLogins) login.get(0)).getLastUsed());
		}
		
		return null;
	}

	@Override
	public void removeUserTokens(String username) {
		Criteria crit = getSessionFactory().getCurrentSession().createCriteria(PersistentLogins.class);
        crit.add(Restrictions.eq("username", username));
        PersistentLogins login = (PersistentLogins) crit.uniqueResult();
        
        if (login != null) {
            delete(login);
        }
        
	}
	
}

15.4.- OAuthClientDAOImpl.java

package co.com.registration.application.repository.impl;

import java.math.BigDecimal;

import javax.persistence.NoResultException;

import org.hibernate.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import co.com.registration.application.model.OauthClientDetails;
import co.com.registration.application.repository.dao.OAuthClientDAO;
import co.com.registration.application.repository.generic.GenericDAOImpl;

@Transactional
@Repository("OAuthClientDAO")
public class OAuthClientDAOImpl extends GenericDAOImpl<OauthClientDetails, String> implements OAuthClientDAO {
	
	public OAuthClientDAOImpl() {
		super(OauthClientDetails.class);
	}

	@Override
	public boolean isClientAvailable(String clientId) {
		Assert.notNull(clientId);
		
		StringBuilder sQuery = new StringBuilder();
		
		sQuery.append("SELECT count(*) \n");
		sQuery.append("FROM ");
		sQuery.append(getClazz().getSimpleName());
		sQuery.append(" c \n");
		sQuery.append("WHERE c.clientId = :ipClientId");
		
		Query query = getSessionFactory().getCurrentSession().createQuery(sQuery.toString());
		query.setParameter("ipClientId", clientId);
		
		Long count = (Long) query.list().get(0);
		
		return count >= 1 ? true : false;
	}

	@Override
	public OauthClientDetails loadClientByName(String clientName) {
		Assert.notNull(clientName);
		
		OauthClientDetails client = null;
		
		StringBuilder sQuery = new StringBuilder();
		
		sQuery.append("SELECT c \n");
		sQuery.append("FROM ");
		sQuery.append(getClazz().getSimpleName());
		sQuery.append(" c \n");
		sQuery.append("WHERE c.clientName = :ipClientName");
		
		
		try{
			Query query = getSessionFactory().getCurrentSession().createQuery(sQuery.toString());
			query.setParameter("ipClientName", clientName);
			
			if (query.list().get(0) instanceof OauthClientDetails){
				client = (OauthClientDetails) query.list().get(0);
			}
			
		}catch (NoResultException nre){
				 System.out.println("No se encontro el cliente --> " + nre.toString());
		}
		
		return client;
	}

	@Override
	public OauthClientDetails getByOauth2Id(BigDecimal oauth2Id) {
		OauthClientDetails client = getSessionFactory().getCurrentSession().load(OauthClientDetails.class, oauth2Id);
		
		return client;
	}

	@Override
	public void eliminarById(BigDecimal oid) {
		OauthClientDetails client = getSessionFactory().getCurrentSession().load(OauthClientDetails.class, oid);
		delete(client);
	}
	
}

16.- Contrucción Capa de Servicios
16.1- UserServicesDao.java

package co.com.registration.application.service.dao;

import java.util.List;

import co.com.registration.application.model.Role;
import co.com.registration.application.model.User;

public interface UserServicesDao {
	
	public void createUser(User u, List<Role> role);
	
	public boolean isUserAvailable(String username);
	
	public User getUserByLogin(String login);
	
	public User actualizar(User u);
	
	public void eliminar(User u);
	
}

16.2- RoleServicesDao.java

package co.com.registration.application.service.dao;

import java.util.List;

import co.com.registration.application.model.Role;

public interface RoleServicesDao {
	
	public List<Role> getAllRoles();
	
	public Role getInfoRole();
	
	public void deleteRole();
	
	public void updateRole();
	
}

16.3- ClientServicesDao.java

package co.com.registration.application.service.dao;

import java.math.BigDecimal;
import java.util.List;

import co.com.registration.application.model.OauthClientDetails;

public interface ClientServicesDao {
	
	public List<OauthClientDetails> getallClient();
	
	public void createClient(OauthClientDetails client);
	
	public boolean isClientAvailable(String clientId);
	
	public OauthClientDetails getClientById(String clientId);
	
	public OauthClientDetails getClientByOauth2Id(BigDecimal oid);
	
	public OauthClientDetails actualizar(OauthClientDetails client);
	
	public void eliminar(OauthClientDetails client);
	
	public void eliminar(BigDecimal oid);
	
	public void eliminar(String clientId);
	
}

17.- Implementación de la Capa de Servicios
17.1.- CustomUserDetailServices.java

package co.com.registration.application.service.security;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import co.com.registration.application.annotation.InfoLogger;
import co.com.registration.application.model.Role;
import co.com.registration.application.repository.dao.UserDao;
import co.com.registration.application.service.dao.UserServicesDao;
import co.com.registration.application.util.Constants;

@Service("customUserDetailsService")
@Transactional
public class CustomUserDetailServices implements UserDetailsService, UserServicesDao {

	@Autowired
	private UserDao userDao;
	
	@Autowired
	@Qualifier("customPasswordEncoder")
    private PasswordEncoder passwordEncoder;
	
	@Override
	@InfoLogger(source = "loadUserByUsername")
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

		co.com.registration.application.model.User user = userDao.loadUserByUsername(username);
		
	   if (user == null)
		   throw new UsernameNotFoundException(String.format(Constants.MSG_ERROR_USUARIO_NO_REGISTRADO, username));

		return new User(user.getLogin(), 
				        user.getPassword(),
						Boolean.valueOf(user.getEnable()), 
						Boolean.valueOf(user.getAccountNonExpired()), 
						Boolean.valueOf(user.getCredentialNonExpired()), 
						Boolean.valueOf(user.getAccountNonLocked()),
						getAuthorities(user.getRoleList())
					   );
	}

	public Collection<? extends GrantedAuthority> getAuthorities(List<Role> role) {
		List<GrantedAuthority> authoritiesList = new ArrayList<GrantedAuthority>(2);

		Iterator<Role> iterRole = role.iterator();

		while (iterRole.hasNext()) {
			Role rol = iterRole.next();
			authoritiesList.add(new SimpleGrantedAuthority(rol.getRole()));
			System.out.println("ROLES --> " + rol.getRole());
		}

		return authoritiesList;
	}
	
	@Override
	public boolean isUserAvailable(String username) {
		
		boolean available = userDao.isUserAvailable(username);

		return available;
	}

	@Override
	public co.com.registration.application.model.User getUserByLogin(String login) {
		return userDao.loadUserByUsername(login);
	}

	@Override
	public co.com.registration.application.model.User actualizar(co.com.registration.application.model.User u) {
		userDao.update(u);	
		return u;
	}

	@Override
	public void eliminar(co.com.registration.application.model.User u) {
		userDao.delete(u.getIdUser().longValue());
	}

	@Override
	public void createUser(co.com.registration.application.model.User u, List<Role> role) {
		u.setPassword(passwordEncoder.encode(u.getPassword()));
		u.setRoleList(role);
		userDao.save(u);
	}

}

17.2.- RoleServiceDaoImpl.java

package co.com.registration.application.service.security;

import org.springframework.stereotype.Service;

@Service("roleServices")
public class RoleServiceDaoImpl {

}

17.3.- ClientServiceDaoImpl.java

package co.com.registration.application.service.security;

import java.math.BigDecimal;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import co.com.registration.application.model.OauthClientDetails;
import co.com.registration.application.repository.dao.OAuthClientDAO;
import co.com.registration.application.service.dao.ClientServicesDao;

@Service("clientServiceDao")
public class ClientServiceDaoImpl implements ClientServicesDao {
	
	@Autowired
	private OAuthClientDAO clientDao;
	
	@Override
	public List<OauthClientDetails> getallClient() {
		return clientDao.getAllRows();
	}
	
	@Override
	public void createClient(OauthClientDetails client) {
		clientDao.save(client);
	}

	@Override
	public boolean isClientAvailable(String clientId) {
		return clientDao.isClientAvailable(clientId);
	}

	@Override
	public OauthClientDetails getClientById(String clientId) {
		return clientDao.getById(clientId);
	}

	@Override
	public OauthClientDetails actualizar(OauthClientDetails client) {
		return clientDao.update(client);
	}

	@Override
	public void eliminar(OauthClientDetails client) {
		clientDao.delete(client);
	}
	
	@Override
	public void eliminar(String clientId) {
		clientDao.delete(clientId);
	}

	@Override
	public OauthClientDetails getClientByOauth2Id(BigDecimal oid) {
		return clientDao.getByOauth2Id(oid);
	}

	@Override
	public void eliminar(BigDecimal oid) {
		clientDao.eliminarById(oid);
	}
	
}

18.- Creando nuestro controlador
18.1.- AppController.java

package co.com.registration.application.controller;

import java.math.BigDecimal;
import java.util.List;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;

import co.com.registration.application.annotation.InfoLogger;
import co.com.registration.application.model.OauthClientDetails;
import co.com.registration.application.service.dao.ClientServicesDao;
import co.com.registration.application.util.Utils;

@Controller
@RequestMapping("/")
@SessionAttributes("roles")
public class AppController {
	
	@Autowired
	ClientServicesDao clientService;
	
	@Autowired
	MessageSource messageSource;
	
	@Autowired
    AuthenticationTrustResolver authenticationTrustResolver;
	
	@Autowired
	PersistentTokenBasedRememberMeServices persistentTokenBasedRememberMeServices;
	
	@RequestMapping(value = { "/", "/list" }, 
			        method = RequestMethod.GET)
	public String listClient(ModelMap model) {

		List<OauthClientDetails> clients = clientService.getallClient();
		model.addAttribute("oauthClientDetails", clients);
		model.addAttribute("loggedinuser", getPrincipal());
		
		return "clientlist";
	}
	
	@RequestMapping(value = { "/newclient" }, 
			        method = RequestMethod.GET)
	public String newClient(ModelMap model) {
		
		OauthClientDetails oauthClientDetails = new OauthClientDetails();
		model.addAttribute("oauthClientDetails", oauthClientDetails);
		model.addAttribute("edit", false);
		model.addAttribute("loggedinuser", getPrincipal());
		
		return "clientregistration";
	}
	
	@RequestMapping(value = { "/newclient" }, 
			        method = RequestMethod.POST)
	@InfoLogger(source = "saveClient")
	public String saveClient(@Valid OauthClientDetails oauthClientDetails, 
			                        BindingResult result,
			                        ModelMap model) {

		if(clientService.isClientAvailable(oauthClientDetails.getClientId())){
			FieldError clientError = new FieldError("client",
					                                "clientId",
					                                messageSource.getMessage("non.unique.clientId", 
					                                		                 new String[]{
					                                									  oauthClientDetails.getClientId()
					                                		                              }, 
					                                		                 Locale.getDefault()));
		    result.addError(clientError);
			return "clientregistration";
		}
		
		oauthClientDetails.setClientId(Utils.generateClientInformation(oauthClientDetails.getClientId()));
		oauthClientDetails.setClientSecret(Utils.generateClientSecret(oauthClientDetails.getClientName()));
		
		clientService.createClient(oauthClientDetails);
		
		model.addAttribute("newClient", oauthClientDetails);		
		model.addAttribute("loggedinuser", getPrincipal());
		return "registrationsuccess";
	}
	
	@RequestMapping(value = { "/edit-client-{oid}" }, method = RequestMethod.GET)
	public String editClient(@PathVariable BigDecimal oid, ModelMap model) {
		
		OauthClientDetails oauthClientDetails = clientService.getClientByOauth2Id(oid);
		model.addAttribute("oauthClientDetails", oauthClientDetails);
		model.addAttribute("edit", true);
		model.addAttribute("loggedinuser", getPrincipal());
		
		return "clientregistration";
	}
	
	@RequestMapping(value = { "/edit-client-{oid}" }, method = RequestMethod.POST)
	public String updateclient(@Valid OauthClientDetails oauthClientDetails, 
				                      BindingResult result,
				                      ModelMap model, 
				               @PathVariable BigDecimal oid) {

		if (result.hasErrors()) {
			return "clientregistration";
		}

		clientService.actualizar(oauthClientDetails);

		model.addAttribute("oauthClientDetails", oauthClientDetails);		
		model.addAttribute("loggedinuser", getPrincipal());
		
		return "registrationsuccess";
	}
	
	@RequestMapping(value = { "/delete-client-{oid}" }, method = RequestMethod.GET)
	public String deleteUser(@PathVariable BigDecimal oid) {
		clientService.eliminar(oid);
		return "redirect:/list";
	}
	
	@RequestMapping(value = "/Access_Denied", method = RequestMethod.GET)
	public String accessDeniedPage(ModelMap model) {
		model.addAttribute("loggedinuser", getPrincipal());
		return "accessdenied";
	}
	
	@RequestMapping(value = "/login", method = RequestMethod.GET)
	public String loginPage() {
		if (isCurrentAuthenticationAnonymous()) {
			return "login";
	    } else {
	    	return "redirect:/list";  
	    }
	}
 
    @RequestMapping(value="/logout", method = RequestMethod.GET)
    public String logoutPage (HttpServletRequest request, HttpServletResponse response){
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null){    
            //new SecurityContextLogoutHandler().logout(request, response, auth);
            persistentTokenBasedRememberMeServices.logout(request, response, auth);
            SecurityContextHolder.getContext().setAuthentication(null);
        }
        return "redirect:/login?logout";
    }
 
    private String getPrincipal(){
        String userName = null;
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
 
        if (principal instanceof UserDetails) {
            userName = ((UserDetails)principal).getUsername();
        } else {
            userName = principal.toString();
        }
        return userName;
    }
     
    private boolean isCurrentAuthenticationAnonymous() {
        final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return authenticationTrustResolver.isAnonymous(authentication);
    }
    
}

19.- Creando anotaciones
19.1.- InfoLogger.java

package co.com.registration.application.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface InfoLogger {
	
	String source();
	
}

21.- Aspectos
21.1.- LogginAspect.java

package co.com.registration.application.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

@Aspect
@Component
public class LogginAspect {
	
	private static final Logger logger = LoggerFactory.getLogger(LogginAspect.class);
	
	/**
	 *

Metodo: Definicion del PointCut controller.

	 *

Descripcion: Este metodo es la definicion del pointcut para identificar todos los metodos anotados con @InfoLogger.

	 */
	@Pointcut("@annotation(co.com.registration.application.annotation.InfoLogger)")
	public void infoLoggerPointcut() {}
	
	/**
	 *

Metodo: Definicion del PointCut controller.

	 *

Descripcion: Este metodo es la definicion del pointcut para identificar todas las clases anotadas con @Controller.

	 */
	//@Pointcut("within(@org.springframework.web.bind.annotation.RestController *)")
	//public void controllerPointcut() {}

	/**
	 *

Metodo: Definicion del PointCut requestMapping.

	 *

Descripcion: Este metodo es la definicion del pointcut para identificar todas las clases anotadas con @RequestMapping.

	 */
	//@Pointcut("within(@org.springframework.web.bind.annotation.RequestMapping *)")
	//public void requestMappingPointcut() {}
	
	/**
	 *

Metodo: Definicion del PointCut.

	 *

Descripcion: Este metodo es la definicion del pointcut para la ejecuci�n de todos lo metodos DAOImpl y que comienzan por get.

	 */
	//@Pointcut("execution(public * co.com.microservice.application.controller.*.obtener*())")
	//public void operacionesGetPointcut(){};
	
	/**
	 *

Metodo: Antes de la Operacion.

	 *

Descripcion: Este metodo se ejecuta antes de cada metodo.

	 * @param jp de tipo JoinPoint con la informacion de Objetos de entrada y salida del metodo
	 */
	//@Before("infoLoggerPointcut() && controllerPointcut() && requestMappingPointcut() && operacionesGetPointcut()")
	@Before("infoLoggerPointcut()")
	public void beforeOper(JoinPoint jp){
		// Impresion en el log
		try{
			Object result = jp.getArgs();
			ObjectMapper objectMapper = new ObjectMapper();			
		    logger.debug("*============================ BEFORE > > > {}", objectMapper.writeValueAsString(result));
	    }catch (JsonProcessingException jpe){    
	    	    logger.error("JsonGenerationException > > > {}", jpe.toString());
		}catch (Throwable e){
			    logger.error("*============================ Throwable > > > {}", e.toString());
		}
	}
	
	/**
	 *

Metodo: Despues de la Operacion.

	 *

Descripcion: Este metodo se ejecuta antes de cada metodo.

	 * @param jp de tipo JoinPoint con la informacion de Objetos de entrada y salida del metodo
	 */
	//@After("infoLoggerPointcut() && controllerPointcut() && requestMappingPointcut() && operacionesGetPointcut()")
	@After("infoLoggerPointcut()")
	public void afterOper(JoinPoint jp){
		// Impresion en el log		
		try{
			Object result = jp.getArgs();
			ObjectMapper objectMapper = new ObjectMapper();			
		    logger.debug("*============================ AFTER > > > {}", objectMapper.writeValueAsString(result));
	    }catch (JsonProcessingException jpe){    
	    	    logger.error("*JsonGenerationException > > > {}", jpe.toString());
		}catch (Throwable e){
			    logger.error("*============================ Throwable > > > {}", e.toString());
		}	
			
	}
	
	/**
	 *

Metodo: Control de Excepciones.

	 *

Descripcion: Este metodo se ejecuta cuando se lanza una excepcion.

	 * @param e de tipo Exception
	 */
	//@AfterThrowing(pointcut="infoLoggerPointcut() && controllerPointcut() && requestMappingPointcut() && operacionesGetPointcut()", throwing="error")
	@AfterThrowing(pointcut="infoLoggerPointcut()", throwing="error")
	public void controlException(JoinPoint joinPoint, Throwable error){
		// Impresion en el log
		logger.debug("*============================ SE PRODUJO UNA EXCEPCION > > > {} CAUSA {}", joinPoint.getSignature().getName(), error);
	}
	
	/**
	 *

Metodo: Impresion de Parametros de entrada.

	 *

Descripcion: Metodo que muestra los valores de los parametros de entrada de cada procedimiento.

	 * @param pjp del tipo ProceedingJoinPoint
	 * @return the object
	 * @throws Throwable the throwable
	 */
	//@Around("infoLoggerPointcut() && controllerPointcut() && requestMappingPointcut() && operacionesGetPointcut()")
	@Around("infoLoggerPointcut()")
	public Object logMethod(ProceedingJoinPoint pjp) throws Throwable{
		// Definicion del objeto a retornar
		Object retval =  null;
		try{
			// Definicion del String que imprimira los valores de los parametros 
			StringBuffer stb = new StringBuffer();
			// Construccion del String
			stb.append("============================ INICIANDO METODO > > > " + pjp.getTarget().getClass().getName());
			stb.append("(");
			// Obtenemos los parametros de entrada de cada procedimiento
			Object[] arg = pjp.getArgs();
			
			// Recorremos los parametros para extraer sus valores
			for (int i = 0; i < arg.length; i++){ stb.append(arg[i]).append(","); } // Validamos la longitud de los parametros if (arg.length > 0) {
                stb.deleteCharAt(stb.length() - 1);
            }
			// Cerramos el String para la impresion de los parametros
			stb.append(")");
			// Asignamos los objetos para retornar
			retval = pjp.proceed();
			// Imprimimos en el Log
			logger.debug("*============================ AROUND > > > {}",stb.toString());
		}catch(Throwable tr){
			   logger.error("============================ ERROR > > > {}", tr);
			   throw tr;
		}
		// Retornamos el valor
		return retval;
	}
	
	/** 
	 *

Metodo: Impresion en el log despues de retornar los valores.

	 *

Descripcion: Metodo que imprime en el log despues de retornar los valores.

	 * @param jp del tipo JoinPoint
	 * @param result del tipo Object
	 * @throws JsonProcessingException 
	 */
	//@AfterReturning(pointcut = "infoLoggerPointcut() && controllerPointcut() && requestMappingPointcut() && operacionesGetPointcut()", returning="result")
	@AfterReturning(pointcut = "infoLoggerPointcut()", returning="result")
	public void logAfterReturning(JoinPoint jp, Object result){
		// Impresion en el log
	    try{
	    	ObjectMapper objectMapper = new ObjectMapper();			
		    logger.debug("*============================ DESPUES DEL RETURNING > > > {}", objectMapper.writeValueAsString(result));
	    }catch (JsonProcessingException jpe){    
	    	    logger.error("JsonGenerationException > > > {}", jpe.toString());
		}
	    
	}
	
}

22.- Utilidades
22.1.- Util.java

package co.com.registration.application.util;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;

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

public class Utils {
	
	public static String generateClientInformation(String clientId){
		int numero = 0;
		try {
			Random codigo = new Random();
			numero = codigo.nextInt(1000) * 50;
		} catch (Exception e) {
				 e.printStackTrace();
		}
		
		StringBuffer sb = new StringBuffer();
		sb.append(clientId);
		sb.append("-");
		sb.append(numero);
		
		return sb.toString();
	}
	
	public static String generateClientSecret(String secret){
		SecureRandom random = null;
		int numero = 0;
		
		try {
			random = SecureRandom.getInstance(Constants.ALGOM_INSTANCE);
			
			Random codigo = new Random();

		    numero = codigo.nextInt(1000) * 10;		    
			
		} catch (NoSuchAlgorithmException e) {
				 e.printStackTrace();
		}
		
		PasswordEncoder encoder = new BCryptPasswordEncoder(10, random);
		
		StringBuffer sb = new StringBuffer();
		
		sb.append(numero);
		sb.append(encoder.encode(secret));
		
		return sb.toString();
	}
	
}

23.- Configuraciones
23.1.- ApplicationContext.java

package co.com.registration.config.application;

import java.util.Properties;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import co.com.registration.application.aspect.LogginAspect;

@Configuration
@EnableTransactionManagement
@ComponentScan({"co.com.registration.config"})
@PropertySource(value = {"classpath:jdbc.properties"})
@EnableAspectJAutoProxy
public class ApplicationContext {
	
	@Autowired
	private Environment env;
	
	@Bean
	public DataSource dataSource() {
		DriverManagerDataSource dataSource = new DriverManagerDataSource();
		
		dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
		dataSource.setUrl(env.getProperty("jdbc.url"));
		dataSource.setUsername(env.getProperty("jdbc.user"));
		dataSource.setPassword(env.getProperty("jdbc.password"));
		
		return dataSource;
	}
	
	@Bean
	public LocalSessionFactoryBean sessionFactory(){
		LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
		
		sessionFactory.setDataSource(dataSource());
		sessionFactory.setPackagesToScan(new String [] {"co.com.registration.application.model"});
		sessionFactory.setHibernateProperties(getHibernateProperties());
		
		return sessionFactory;
	}

	private Properties getHibernateProperties() {
		Properties prop = new Properties();
		
		prop.put("hibernate.dialect", env.getProperty("oracle.dialect"));
		prop.put("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
		prop.put("hibernate.format_sql", env.getProperty("hibernate.format_sql"));
		prop.put("hibernate.query.substitutions", env.getProperty("hibernate.query.substitutions"));
		prop.put("hibernate.connection.release_mode", env.getProperty("hibernate.connection.release_mode"));
		prop.put("hibernate.generate_statistics", env.getProperty("hibernate.generate_statistics"));
		
		return prop;
	}
	
	@Bean
	@Autowired
	public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {		
		HibernateTransactionManager txtManager = new HibernateTransactionManager();
		txtManager.setSessionFactory(sessionFactory);
		
		return txtManager;		
	}
	
	@Bean 
    public LogginAspect myAspect() {
        return new LogginAspect();
    }

	
}

24.2.- SecurityConfig.java

package co.com.registration.config.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	
	@Autowired
    @Qualifier("customUserDetailsService")
    UserDetailsService userDetailsService;
 
    @Autowired
    @Qualifier("customPersistentTokenRepository")
    PersistentTokenRepository tokenRepository;
 
    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
        auth.authenticationProvider(authenticationProvider());
    }
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/", "/list")
            .access("hasRole('USER') or hasRole('ADMIN')")
            .antMatchers("/newclient/**", "/delete-client-*")
            .access("hasRole('ADMIN')")
            .antMatchers("/edit-client-*")
            .access("hasRole('ADMIN')")
           .and()
            .formLogin()
            .loginPage("/login")
            .loginProcessingUrl("/login")
            .failureUrl("/login?error")
            .usernameParameter("username")
            .passwordParameter("password")
           .and()
            .rememberMe()
            .rememberMeParameter("remember-me")
            .tokenRepository(tokenRepository)
            .tokenValiditySeconds(86400)
           .and()
		    .logout().logoutSuccessUrl("/login?logout")
           .and()
            .csrf()
           .and()
            .exceptionHandling()
            .accessDeniedPage("/Access_Denied");
    }
 
    @Bean("customPasswordEncoder")
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
 
    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsService);
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        return authenticationProvider;
    }
 
    @Bean
    public PersistentTokenBasedRememberMeServices getPersistentTokenBasedRememberMeServices() {
        PersistentTokenBasedRememberMeServices tokenBasedservice = new PersistentTokenBasedRememberMeServices("remember-me", userDetailsService, tokenRepository);
        return tokenBasedservice;
    }
 
    @Bean
    public AuthenticationTrustResolver getAuthenticationTrustResolver() {
        return new AuthenticationTrustResolverImpl();
    }  
	
}

24.3.- MvcConfig.java

package co.com.registration.config.servlet;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

import co.com.registration.config.security.SecurityConfig;

@EnableWebMvc
@Configuration
@ComponentScan({ "co.com.registration" })
@Import({ SecurityConfig.class })
public class MvcConfig  extends WebMvcConfigurerAdapter {
	
	@Bean
	public InternalResourceViewResolver viewResolver() {
		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
		viewResolver.setViewClass(JstlView.class);
		viewResolver.setPrefix("/WEB-INF/views/");
		viewResolver.setSuffix(".jsp");
		return viewResolver;
	}
	
	@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("/static/");
    }
     
    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("messages");
        return messageSource;
    }
     
    @Override
    public void configurePathMatch(PathMatchConfigurer matcher) {
        matcher.setUseRegisteredSuffixPatternMatch(true);
    }
	
}

24.4.- RestSecurityInit.java

package co.com.registration.config.servlet;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

public class RestSecurityInit extends AbstractSecurityWebApplicationInitializer {

}

24.5.- WebInicializer.java

package co.com.registration.config.servlet;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import co.com.registration.config.application.ApplicationContext;

public class WebInicializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class[] { ApplicationContext.class, MvcConfig.class };
	}

	@Override
	protected Class<?>[] getServletConfigClasses() {
		return null;
	}

	@Override
	protected String[] getServletMappings() {
		return new String[] {"/"};
	}

}

25.- Recursos
25.1.- jdbc.properties

# * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# * Parametros de Conexion con la Base de Datos Oracle  *
# * * * * * * * * * * * * * * * * * * * * * * * * * * * *
jdbc.driverClassName=oracle.jdbc.OracleDriver
jdbc.user=application
jdbc.password=application
jdbc.url=jdbc:oracle:thin:@localhost:1521:XE

# * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# *      Parametros de Configuracion de hibernate       *
# * * * * * * * * * * * * * * * * * * * * * * * * * * * *
oracle.dialect=org.hibernate.dialect.Oracle10gDialect
hibernate.show_sql=true
hibernate.query.substitutions=true 'T', false 'F'
hibernate.connection.release_mode=after_transaction
hibernate.generate_statistics=true
hibernate.format_sql=true
# * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# *   Parametros del pool de conexiones para c3p0       *
# * * * * * * * * * * * * * * * * * * * * * * * * * * * *
c3p0.minPoolSize=5
c3p0.maxPoolSize=20
c3p0.timeout=300
c3p0.max_statement=50
c3p0.testConnectionOnCheckout=false

25.2.- log4j.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
<log4j:configuration debug="false">

    <appender name="file" class="org.apache.log4j.DailyRollingFileAppender">
        <param name="File" value="${catalina.home}/logs/application_logger.log" />
        <param name="Append" value="true" />
        <param name="Threshold" value="ALL" />
        <param name="MaxFileSize" value="1MB" />
        <param name="MaxBackupIndex" value="1" />
        <param name="DatePattern" value="_yyyy-MM-dd" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%-5p %d [%t] %c: %m%n" />
        </layout>
    </appender>

    <appender name="console" class="org.apache.log4j.ConsoleAppender">
        <param name="Append" value="true" />
        <param name="Threshold" value="ALL" />        
        <param name="DatePattern" value="_yyyy-MM-dd" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n" />
        </layout>
    </appender>

    <root>
        <level value="DEBUG" />
        <appender-ref ref="file" />
        <appender-ref ref="console" />
    </root>

</log4j:configuration>

25.3.- messages.properties

NotEmpty.user.firstName=First name can not be blank.
NotEmpty.user.lastName=Last name can not be blank.
NotEmpty.user.email=Email can not be blank.
NotEmpty.user.password=Password can not be blank.
NotEmpty.user.ssoId=SSO ID can not be blank.
NotEmpty.user.userProfiles=At least one profile must be selected.
non.unique.clientId=Client ID {0} already exist. Please fill in different value.

25.3.- messages_es.properties

NotEmpty.user.firstName=First name can not be blank.
NotEmpty.user.lastName=Last name can not be blank.
NotEmpty.user.email=Email can not be blank.
NotEmpty.user.password=Password can not be blank.
NotEmpty.user.ssoId=SSO ID can not be blank.
NotEmpty.user.userProfiles=At least one profile must be selected.
non.unique.clientId=Client ID {0} already exist. Please fill in different value.

25.4.- message_es.properties

non.unique.clientId=Client ID {0} already exist. Please fill in different value.

26.- Creación de las Vistas JSP
26.1.- login.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<%@ page isELIgnored="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
     <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
     <title>Login page</title>
     <link href="<c:url value='/static/css/style.css' />" rel="stylesheet"></link>
</head>

<body>
	<div class="container">
	 	<div class="container-login">
	 		<c:url var="loginUrl" value="/login" />
			<form action="${loginUrl}" method="post" class="form-horizontal">
				<div class="imgcontainer">
					<img src="http://www.freeiconspng.com/uploads/user-login-icon-14.png"/>
	  			</div>
	  			
				<c:if test="${param.error != null}">
					<div class="alert alert-danger">
						<p>Usuario Invalido.</p>
					</div>
				</c:if>
				<c:if test="${param.logout != null}">
					<div class="alert alert-success">
						<p>Sesion cerrada exitosamente!</p>
					</div>
				</c:if>
				
				<input type="text" class="inputText" id="username" name="username" placeholder="Usuario" required> 
				
				<br> 
				
				<input type="password" class="inputText" id="password" name="password" placeholder="Password" required>
	
				<div class="input-group input-sm">
					<div>
						<label><input type="checkbox" id="rememberme" name="remember-me"> Remember Me</label>
					</div>
				</div>
				<input type="hidden" name="${_csrf.parameterName}"
					value="${_csrf.token}" />
	
				<div>
					<input type="submit" value="Log in" class="botones">
				</div>
				
				<div class="" style="background-color:#f1f1f1">
				    <input type="submit" value="Cancelar" class="cancelbtn">
				    <span class="psw"><a class="ref-edit" href="#">Registrar</a></span>
			   </div>
			</form>
	 	</div>
		
	</div>
</body>
</html>

26.2.- clientlist.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<%@ page isELIgnored="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="sec"
	uri="http://www.springframework.org/security/tags"%>

<html>

	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
		<title>Lista Clientes OAUTH2</title>
		<link href="<c:url value='/static/css/style.css' />" rel="stylesheet"></link>
	</head>

	<body>
		<div class="container">
			<%@include file="authheader.jsp"%>
			<div class="container-list">
				<!-- Default panel contents -->
				<div class="titulo">
					<h2>Listado de Clientes</h2>
				</div>
				
				<br>
				
				<div class="lista">
					<table class="gridtable">
						<thead>
							<tr>
								<th>Client Name</th>
								<th>Resource Ids</th>
								<th>Authorized Grant Types</th>
								<th>Authories</th>
								<th>AccessToken Validity</th>
								<th>RefreshToken Validity</th>
								<th>Auto Approve</th>
								<sec:authorize access="hasRole('ADMIN') or hasRole('USER')">
									<th width="100"></th>
								</sec:authorize>
								<sec:authorize access="hasRole('ADMIN')">
									<th width="100"></th>
								</sec:authorize>
	
							</tr>
						</thead>
						<tbody>
							<c:forEach items="${oauthClientDetails}" var="clients">
								<tr>
									<td>${clients.clientName}</td>
									<td>${clients.resourceIds}</td>
									<td>${clients.authorizedGrantTypes}</td>
									<td>${clients.authorities}</td>
									<td>${clients.accessTokenValidity}</td>
									<td>${clients.refreshTokenValidity}</td>
									<td>${clients.autoapprove}</td>
	
									<sec:authorize access="hasRole('ADMIN') or hasRole('USER')">
										<td><a
											href="<c:url value='/edit-client-${clients.oid}' />"
											class="ref-edit">Editar</a></td>
									</sec:authorize>
									<sec:authorize access="hasRole('ADMIN')">
										<td><a
											href="<c:url value='/delete-client-${clients.oid}' />"
											class="ref-delete">Eliminar</a></td>
									</sec:authorize>
								</tr>
							</c:forEach>
						</tbody>
					</table>
				</div>
				
				<br>
				
				<sec:authorize access="hasRole('ADMIN')">
					<div class="lista">
						<a class="ref-register" href="<c:url value='/newclient' />">Registrar Cliente</a>
					</div>
				</sec:authorize>
			</div>			
		</div>
	</body>
</html>

26.3.- clientregistration.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>

<head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
	<title>Registro Clientes</title>
	<link href="<c:url value='/static/css/style.css' />" rel="stylesheet"></link>
</head>

<body>
 	<div class="container">
		<%@include file="authheader.jsp" %>
		<div class="container-standart">
			<div class="titulo">
				<h2>Formulario Registro Clientes</h2>
			</div>
					
		 	<form:form method="POST" modelAttribute="oauthClientDetails" class="form-horizontal">
				<form:input type="hidden" path="oid" id="oid"/>
				
				<div class="row">
					<div class="form-group col-md-12">
						<label class="col-md-3 control-lable" for="clientId">Client Id</label>
						<div class="col-md-7">
							<form:input type="text" path="clientId" id="clientId" class="form-control input-sm"  required="required"/>
							<div class="has-error">
								<form:errors path="clientId" class="help-inline"/>
							</div>
						</div>
					</div>
				</div>
				
				<div class="row">
					<div class="form-group col-md-12">
						<label class="col-md-3 control-lable" for="clientName">Client Name</label>
						<div class="col-md-7">
							<form:input type="text" path="clientName" id="clientName" class="form-control input-sm" required="required"/>
							<div class="has-error">
								<form:errors path="clientName" class="help-inline"/>
							</div>
						</div>
					</div>
				</div>
		
				<div class="row">
					<div class="form-group col-md-12">
						<label class="col-md-3 control-lable" for="resourceIds">Resource Ids</label>
						<div class="col-md-7">
							<form:input type="text" path="resourceIds" id="resourceIds" class="form-control input-sm" required="required"/>
							<div class="has-error">
								<form:errors path="resourceIds" class="help-inline"/>
							</div>
						</div>
					</div>
				</div>
				
				<c:choose>
					<c:when test="${edit}">
						<div class="row">
							<div class="form-group col-md-12">
								<label class="col-md-3 control-lable" for="clientSecret">Client Secret</label>
								<div class="col-md-7">
									<form:input type="text" path="clientSecret" id="clientSecret" class="form-control input-sm" readonly="true"/>										
								</div>
							</div>
						</div>
					</c:when>								
				</c:choose>
				
				<div class="row">
					<div class="form-group col-md-12">
						<label class="col-md-3 control-lable" for="scope">Scope</label>
						<div class="col-md-7">
							<form:select path="scope" multiple="true" itemValue="id" itemLabel="type" class="form-control input-sm" required="required" >
								<form:option value="read"/>
								<form:option value="write"/>
							</form:select>
							<div class="has-error">
								<form:errors path="scope" class="help-inline"/>
							</div>
						</div>
					</div>
				</div>
		
				<div class="row">
					<div class="form-group col-md-12">
						<label class="col-md-3 control-lable" for="authorizedGrantTypes">Authorized Grant Types</label>
						<div class="col-md-7">
							<form:select path="authorizedGrantTypes" multiple="true" itemValue="id" itemLabel="type" class="form-control input-sm" required="required">
								<form:option value="password"/>
								<form:option value="refresh_token"/>
								<form:option value="client_credential"/>
							</form:select>
							<div class="has-error">
								<form:errors path="authorizedGrantTypes" class="help-inline"/>
							</div>
						</div>
					</div>
				</div>
		
				<div class="row">
					<div class="form-group col-md-12">
						<label class="col-md-3 control-lable" for="webServerRedirectUri">Web Server Redirect Uri</label>
						<div class="col-md-7">
							<form:input type="text" path="webServerRedirectUri" id="webServerRedirectUri" class="form-control input-sm" required="required" />
							<div class="has-error">
								<form:errors path="webServerRedirectUri" class="help-inline"/>
							</div>
						</div>
					</div>
				</div>
		
				<div class="row">
					<div class="form-group col-md-12">
						<label class="col-md-3 control-lable" for="authorities">Authorities</label>
						<div class="col-md-7">
							<form:select path="authorities" multiple="true" itemValue="id" itemLabel="type" class="form-control input-sm" required="required">
								<form:option value="ADMIN"/>
								<form:option value="USER"/>
								<form:option value="GUEST"/>
							</form:select>
							<div class="has-error">
								<form:errors path="authorities" class="help-inline"/>
							</div>
						</div>
					</div>
				</div>
				
				<div class="row">
					<div class="form-group col-md-12">
						<label class="col-md-3 control-lable" for="accessTokenValidity">AccessToken Validity</label>
						<div class="col-md-7">
							<form:input type="text" path="accessTokenValidity" id="accessTokenValidity" class="form-control input-sm" required="required"/>
							<div class="has-error">
								<form:errors path="accessTokenValidity" class="help-inline"/>
							</div>
						</div>
					</div>
				</div>
				
				<div class="row">
					<div class="form-group col-md-12">
						<label class="col-md-3 control-lable" for="refreshTokenValidity">RefreshToken Validity</label>
						<div class="col-md-7">
							<form:input type="text" path="refreshTokenValidity" id="refreshTokenValidity" class="form-control input-sm" required="required" />
							<div class="has-error">
								<form:errors path="refreshTokenValidity" class="help-inline"/>
							</div>
						</div>
					</div>
				</div>
				
				<div class="row">
					<div class="form-group col-md-12">
						<label class="col-md-3 control-lable" for="autoapprove">Auto Approve</label>
						<div class="col-md-7">
							<form:input type="text" path="autoapprove" id="autoapprove" class="form-control input-sm" required="required"/>
							<div class="has-error">
								<form:errors path="autoapprove" class="help-inline"/>
							</div>
						</div>
					</div>
				</div>
		
				<div class="row">
					<div class="form-actions floatRight">
						<c:choose>
							<c:when test="${edit}">
								<input type="submit" value="Update" class="botones2"/>  <a class="ref-delete" href="<c:url value='/list' />">Cancel</a>
							</c:when>
							<c:otherwise>
								<input type="submit" value="Register" class="botones2"/>  <a class="ref-delete" href="<c:url value='/list' />">Cancel</a>
							</c:otherwise>
						</c:choose>
					</div>
				</div>
			</form:form>
		</div>
	</div>
</body>
</html>

26.5.- registrationsuccess.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
	<title>Registration Confirmation Page</title>
	<link href="<c:url value='/static/css/style.css' />" rel="stylesheet"></link>
</head>
<body>
	<div class="container">
		<%@include file="authheader.jsp" %>
		<div class="container-list">
			<div class="titulo">
				<h2>Cliente Registrado Exitosamente!</h2>
			</div>
			
			<div class="lista">
		        <table class="gridtable">	
		        	<thead>
						<tr>
							<th>Atributos</th>
							<th>Valores</th>
						</tr>
					</thead>
					<tbody>
						<tr>
			                <td>Client Id:</td>
			                <td>${oauthClientDetails.clientId}</td>
			            </tr>
			            <tr>
			                <td>Client Name:</td>
			                <td>${oauthClientDetails.clientName}</td>
			            </tr>
			            <tr>
			                <td>Client Secret:</td>
			                <td>${oauthClientDetails.clientSecret}</td>
			            </tr>
			            <tr>
			                <td>Resource Ids:</td>
			                <td>${oauthClientDetails.resourceIds}</td>
			            </tr>
			            <tr>
			                <td>Scopes:</td>
			                <td>${oauthClientDetails.scope}</td>
			            </tr>
			 			<tr>
			                <td>Grant Types:</td>
			                <td>${oauthClientDetails.authorizedGrantTypes}</td>
			            </tr>
			            <tr>
			                <td>Redirect URI:</td>
			                <td>${oauthClientDetails.webServerRedirectUri}</td>
			            </tr>
			            <tr>
			                <td>Authorities:</td>
			                <td>${oauthClientDetails.authorities}</td>
			            </tr>
			            <tr>
			                <td>Access Token Validity:</td>
			                <td>${oauthClientDetails.accessTokenValidity}</td>
			            </tr>
			            <tr>
			                <td>Refresh Token Validity:</td>
			                <td>${oauthClientDetails.refreshTokenValidity}</td>
			            </tr>
			            <tr>
			                <td>Auto Approve:</td>
			                <td>${oauthClientDetails.autoapprove}</td>
			            </tr>
					</tbody>
		        </table>
		    </div>
		    
			<div class="lista">
				<span class="well floatRight">
					<a class="ref-register"href="<c:url value='/list' />">Listado Clientes</a>
				</span>
			</div>
		</div>
	</div>
</body>

</html>

26.6.- authheader.jsp

<div class="">
		<span>Bienvenido <strong>${loggedinuser}</strong>.</span> 
		<span class="floatingRight"><a class="ref-delete" href="<c:url value="/logout" />">Logout</a></span>
</div>

26.7.- accessdenied.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
	<title>AccessDenied page</title>
</head>
<body>
	<div class="generic-container">
		<div class="authbar">
			<span>Lo sentimos <strong>${loggedinuser}</strong>, no está autorizado para consultar esta página.</span> <span class="floatRight"><a href="<c:url value="/logout" />">Logout</a></span>
		</div>
	</div>
</body>
</html>

27.- Recursos Web
27.1.- style.css

/* Bordered form */
form {
    border: 3px solid #f1f1f1;
}

/* Full-width inputs */
input[type=text], input[type=password] {
    width: 100%;
    padding: 12px 20px;
    margin: 8px 0;
    display: inline-block;
    border: 1px solid #ccc;
    box-sizing: border-box;
}

input[type=checkbox] {
    padding-left: 35px;
    height: 30px;
    display: inline-block;
    line-height: 30px;
    background-repeat: no-repeat;
    background-position: 0 0;
    font-size: 100px;
    vertical-align: middle;
    cursor: pointer;
}

/* Set a style for all buttons */
.botones {
    background-color: #4CAF50;
    color: white;
    padding: 14px 20px;
    margin: 8px 0;
    border: none;
    cursor: pointer;
    width: 100%;
}

.botones2 {
    background-color: #4CAF50;
    color: white;
    padding: 10px 18px;
    margin: 8px 0;
    border: none;
    cursor: pointer;
    width: auto;    
}

/* Extra style for the cancel button (red) */
.cancelbtn {
    width: auto;
    padding: 10px 18px;
    margin: 8px 0;
    border: none;
    color: white;
    background-color: #f44336;
}

/* Center the avatar image inside this container */
.imgcontainer {
    text-align: center;
    margin: 24px 0 12px 0;
}

/* Avatar image */
img.avatar {
    width: 40%;
    border-radius: 50%;
}

/* Add padding to containers */
.container {
    padding: 16px;
    width : 91%;
	min-height : 500px;
	margin : 50px auto;
	box-shadow : 2px 2px 10px #888;
	background-color : #fff !important;
	padding-bottom : 70px;
	font-family : Verdana;
	font-size : 12px;
	font-weight : normal; 
	font-style : normal;
	border-radius : 7px 7px 7px 7px;
	position : relative;
}

.container-login {
    padding: 16px;
    width : 30%;
	min-height : 150px;
	margin : 50px auto;
	background-color : #fff !important;
	padding-bottom : 70px;
	font-family : Verdana;
	font-size : 12px;
	font-weight : normal; 
	font-style : normal;
}

.container-standart{
	padding: 16px;
    width : 80%;
	min-height : 500px;
	margin : 50px auto;
	box-shadow : 2px 2px 10px #888;
	background-color : #fff !important;
	padding-bottom : 70px;
	font-family : Verdana;
	font-size : 12px;
	font-weight : normal; 
	font-style : normal;
	border-radius : 7px 7px 7px 7px;
	position : relative;
}

.container-list{
	padding: 16px;
    width : 91%;
	min-height : 500px;
	margin : 50px auto;
	box-shadow : 2px 2px 10px #888;
	background-color : #fff !important;
	padding-bottom : 70px;
	font-family : Verdana;
	font-size : 12px;
	font-weight : normal; 
	font-style : normal;
	border-radius : 7px 7px 7px 7px;
	position : relative;
}

.titulo{
	margin : auto;
	background-color : #fff !important;
	padding : 10px;		
	/*border:1px solid #C8C8C8;	
	border-radius : 1px 1px 1px 1px;*/	
	vertical-align: middle;
    text-align: left;	
}

h2{
	font-family : Verdana;
	font-size : 20px;
	font-weight : normal; 
	font-style : normal;
	color : #8f8f8f;
}

/* The "Forgot password" text */
span.psw {
    float: right;
    padding-top: 16px;
}

/* Change styles for span and cancel button on extra small screens */
@media screen and (max-width: 300px) {
    span.psw {
        display: block;
        float: none;
    }
    .cancelbtn {
        width: 100%;
    }
}

.floatingRight{
	display: block;
    float: right;
}

table.gridtable {
	font-family: verdana,arial,sans-serif;
	font-size:11px;
	color:#333333;
	border-width: 10px;
	border-color: #666666;
	border-collapse: collapse;
	width: 100%;
	height: 100px;
}

table.gridtable th {	
	border-width: 1px;
	padding: 8px;
	border-style: solid;
	border-color: #ffffff;
	color: #ffffff;
	background-color: #4CAF50;
	height: 50px;
}

table.gridtable td {
	border-width: 1px;
	padding: 8px;
	border-style: solid;
	border-color: #ffffff;
	background-color: #ffffff;
	text-align: center;
}

.ref-edit {
	color: #ffffff;
  	font-size: 12px;
  	background: #3498db;
  	padding: 10px 20px 10px 20px;
  	text-decoration: none;
    margin-bottom: 50px;
    box-shadow: none;
    height: 15%;
}
.ref-edit, .ref-edit:link, .ref-edit:visited {
    color: #FFFFFF;
    background-color: #4CAF50;
}
.ref-edit, .ref-edit-hover-blue:hover {
    color: #fff!important;
    background-color: #2196F3!important;
}

.ref-delete {
	color: #ffffff;
  	font-size: 12px;
  	background: #f44336;
  	padding: 10px 20px 10px 20px;
  	text-decoration: none;
    margin-bottom: 5px;
    box-shadow: none;
}
.ref-delete, .ref-delete:link, .ref-delete:visited {
    color: #FFFFFF;
    background-color: #f44336;
}
.ref-delete, .ref-delete-hover-blue:hover {
    color: #fff!important;
    background-color: #f44336!important;
}

.ref-register {
	color: #ffffff;
  	font-size: 12px;
  	width : 10%;
  	background: #4CAF50;
  	padding: 10px 20px 10px 20px;
  	text-decoration: none;
    margin-bottom: 5px;
    box-shadow: none;
}
.ref-register, .ref-register:link, .ref-register:visited {
    color: #FFFFFF;
    background-color: #4CAF50;
}
.ref-register, .ref-register-hover-blue:hover {
    color: #fff!important;
    background-color: #4CAF50!important;
}

.lista{
	margin : auto;
	background-color : #fff !important;
	padding : 10px;		
	vertical-align: middle;
    text-align: left;	
}

28. Ejecución

28.1.- Autenticarnos en la aplicación

mvc_ejecucion_2 mvc_ejecucion_3

28.2.- Validando Remember Me

mvc_ejecucion_4 mvc_ejecucion_5 mvc_ejecucion_6

28.3.- Pantalla Bienvenida y Listado de Clientes

mvc_ejecucion_7

28.4.- Agregar un nuevo cliente

mvc_ejecucion_8

28.5.- Resumen creación del cliente

mvc_ejecucion_9

28.6.- Obteniendo un nuevo Oaut2 Token con el ClientId y el ClientSecret

curl -X POST -d ‘grant_type=password&client_id=android-app-5800&client_secret=7200$2a$10$wHT8exj65bfEQMTAoNmZBe7jxjxAzZiyJFeA0KMIfZp/UahKaeQee&username=root&password=123456’ ‘http://localhost:8086/MicroServices/oauth/token&#8217; | json_pp

mvc_ejecucion_1028.7.- Consumiendo el servicio Rest

curl -X GET -H ‘Content-Type: application/json’ -H ‘Authorization: Bearer 9b4df815-304a-4156-9dc0-ab3aeffbb38e’ ‘http://localhost:8086/MicroServices/api/v1.0/productos&#8217; | json_pp

mvc_ejecucion_12

28.8.- Listado de clientes registrados

mvc_ejecucion_13 mvc_ejecucion_9_1

29. Código Fuente

Puedes descargar el código fuente

20 comentarios sobre “Spring MVC + Spring Security + Remember Me + Hibernate + Maven …

  1. Hola!!!
    Me manda errores cuando quiero persisitir un registro, especificamente en la clase “OauthClientDetails”
    en el campo “oid” -> sequenceName = “SQ_OAUTH”
    —————————————————————
    @Id
    @Basic(optional = false)
    @NotNull
    @Column(name = “OID”, nullable = false, precision = 0, scale = -127)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = “OAUTH_SEQ”)
    @SequenceGenerator(name = “OAUTH_SEQ”, sequenceName = “SQ_OAUTH”, allocationSize = 1)
    private BigDecimal oid;
    —————————————————————
    Con respecto al ejercicio anterior veo que cambio un poco la tabla “oauth_client_details”, le agregaste el campo “OID”, ya genere la tabla nueva con respecto a la clase “OauthClientDetails” que muestras aqui,
    pero revisando la documentacion de jpa cuando utilizas “@SequenceGenerator”, en la base de datos se debe especificar el tipo de incremento no? que tomara el ID.
    Espero puedas proporcionar la Base de Datos.

    Gracias!!!

  2. Ya lo solucione 😀 lo que pasa que uso mysql por que todavia no me adentro mucho a oracle, pero le cambie para que sea autoncremental y ya se soluciono.
    Gracias por responder, en tu pasado articulo igual tuve un problema en la tabla “OAUTH_CLIENT_DETAILS” en el campo “autoapprove” me mandaba error por que se pasaba nulo, pero gracias a que lei los comentarios lo solucione 😀

    1. Saludos Angel,

      excelente que lo solucionaras, la verdad he hecho varios cambios al proyecto y creo que por ahí se me fueron varios, no he tenido tiempo de revisar por el trabajo, a penas tenga tiempo reviso y subo los nuevos cambios, excelente que te sirva el blog.

  3. Hola
    No aparece el archivo con el código fuente para descargar. Estoy haciendo una API REST con Spring MVC, Spring Security, Hibernate. Te agradeceria si me podrias proporcionar el código fuente para poder guiarme en lo que respecta la seguridad con spring security. Gracias
    Correo: cristianwic@gmail.com

      1. Gracias por la respuesta, muy amable de tu parte y gracias por tu ayuda… Como dije en el comentario anterior. Estoy haciendo una API Rest, y lo que necesito es ponerle seguridad, Spring Security oauth2 me sirve para autenticar a mis usuarios de mi base de datos? el acceso a los usuarios(login) mediante AJAX. Hasta ahora lo que tengo hecho es hacer las peticiones mediante AJAX hacia el servidor donde se encuentra la API Rest, hasta el momento cualquier usuario que haga la solicitud a una determinada URL tiene acceso a los datos, lo que quiero conseguir es que solo usuarios autenticados mediante un formulario de login mediante AJAX tengan acceso a la API Rest, dichos usuarios tienen roles asignados.

      2. Saludos Christian,

        los servicios rest de ejemplo que he publicado los he enfocado mas que todo a consumirlos desde una aplicación movil, si tu solución está direccionada a la web como tal te sugiero enfocarla como lo ejemplifican en este link (http://websystique.com/springmvc/spring-mvc-4-and-spring-security-4-integration-example/) igual tambien podrías usar Oauth2 y securizar tus recursos pero ya depende de tí y los requerimientos de tu solución

  4. Entiendo lo que me dices. Yo lo que tengo es la API Rest corriendo en el servidor, y como dices esta API va ser consumida desde otro entorno como un dispositivo movil, o sea, por un lado tengo la API y otra muy aparte la aplicación para el cliente enfocado para móvil. En el link que me pones, ciertamente esta enfocado para web, y al momento de hacer la autenticacion creas un formulario de login, pero para una api rest no se puede enviar un formulario para el logeo de usuarios, creo que el login se tendria que hacer mediante una peticion ajax configurada con spring security o algo parecido, y una vez que el usuario de halla logeado en la aplicacion del cliente, este pueda tener acceso a los recursos que solicita hacia la API rest, teniendo en cuenta que para cada peticion creo que se tiene que enviar las credenciales de autenticacion, no tengo esto muy claro y estoy algo confuso. Espero me halla podido dejar entender. ¿Cual seria una buena solución de darle seguridad a la api rest mediante spring security con lo que estoy diciendo? ¿seria bueno utilizar oauth2?

  5. bueos días Christian,

    te entiendo perfectamente, si vas a consumir tu api rest desde un cliente movil entonces si vaya fijo con spring security + spring oauth2, con oauth2 solo tienes que enviar las credenciales 1 vez y el servidor de authorización te devulve un token, este token tienes que enviarlo con cada petición al servidor por el recurso que quieres consumir, adicionalmente cuando solicitas por primera vez el token también viene un refresh token que no es mas que otro token que te permite solicitar uno nuevo cuando el primero ya expiró este refresh token lo usas cada vez que el token expire y recibiras un error http 401, revisa mi entrada de Spring security y Oauth2 para que clarifiques igual ahí está un ejercicio completo del concepto.

    1. Gracias mi estimado por tu respuesta, inmediatamente me pondré en ello. Espero si me surge alguna duda o complicación poder venir por aquí y poder recibir tu ayuda de tu conocimiento. Gracias, que tengas un excelente día.

  6. Hola, buen día, nuevamente por aquí, bueno ya implementé oauth2, ahora en lo que estoy algo perdido es en como hacer la llamada ajax para hacer el logeo (como va extructurado la URL hacia un logeo) o desde Postman. y como podría hacer la url para las llamadas ajax de mis recursos, anteriormente cuando aun no implementaba oauth2 solo ponía esto: http://localhost:8084/GolwinAPI/api/v1/competiciones/1
    y el servidor me respondía correctamente sin ningun problema.
    He intentado hacerlo de la manera que pones en el tutorial pero no he logrado tener éxito.
    Podrías explicarme por favor como es que podría implementar las url, y de donde saco los valores de los parámetros?
    Te lo agradecería mucho. Que tengas un excelente día.

    1. Saludos Christian

      para obtener el token tienes que llamar el recurso oauth/token que viene de caja en spring security oauth2 y este se acopla al contexto de tu aplicación:
      1.- http://localhost:8082/MicroServices/oauth/token?grant_type=password&client_id=clientapp&client_secret=987654321&username=root&password=123456

      2.- y una vez que tienes el token ya lo envías especificando el recurso que quieres consumir:
      http://localhost:8082/MicroServices/api/v1.0/clientes/4567654999?access_token=9eb94afc-55fe-4a7b-b4f2-9d87e7e0cfcd

      1. Gracias por tu respuesta. Aun asi tengo algunas dudas, de donde obtengo los valores de las variables como el client_id, client_secret.
        Supongo que el username y password se refieren a los valores del logeo del usuario. Estos valores yo los quiero obtener de mi base de datos en la cual tengo a mis usuarios con sus respectivos roles, en donde username en mi tabla de usuarios yo lo tengo nombrado como usualias, y en password lo tengo nombrado como usupassw.
        puedo hacer esto o tengo que ponerlo como dices? ya lo he intentando pero no he logrado tener éxito.

      2. Saludos Christian,

        los valores client_id y client_secret son valores que le permiten identificar que la aplicación cliente que pretende obtener el token es una aplicación valida, google, facebook, github etc… todas tienen sus servicios oauth2, para usar a google por ejemplo como proveedor de token tu en la consola web de google registras los datos de tu aplicación cliente y google te devuelve el client_id y el client_secret que le permite identificar que es un cliente valido y autorizado para recibir un token para consumir tus recursos, en el caso de ejemplo de mi entrada sobre spring yo guardo mi información del cliente en una la tabla OAUTH_CLIENT_DETAILS y el motor de spring security se encarga de consultarla y validar si es un cliente autorizado, y yo puedo registrar todos los clientes que quiera para consumir mis recursos, por ejemplo puedo tener mi recurso calculadora y crear un registro en la tabla que mencioné antes para una aplicación en IOS, otra para ANdroid otra para una app desktop o web etc…

  7. Gracias por la pronta respuesta, me pondré a trabajar en ello, ya lo tengo mas claro.
    Gracias, que tengas un excelente día.

  8. Hola, nuevamente por aca. Al momento de realizar la peticion del token me salta este error como respuesta:
    {
    “error”: “unauthorized”,
    “error_description”: “com.golwin.application.model.OauthClientDetails cannot be cast to java.lang.Long”
    }
    status: 401 No Autorizado
    estoy usando postman.
    Me he dado cuenta que en la parte de la implementacion de esto:
    @Override
    public boolean isClientAvailable(String clientId) {
    Assert.notNull(clientId);

    StringBuilder sQuery = new StringBuilder();

    sQuery.append(“SELECT count(*) \n”);
    sQuery.append(“FROM “);
    sQuery.append(getClazz().getSimpleName());
    sQuery.append(” c \n”);
    sQuery.append(“WHERE c.clientId = :ipClientId”);

    Query query = getSessionFactory().getCurrentSession().createQuery(sQuery.toString());
    query.setParameter(“ipClientId”, clientId);

    Long count = (Long) query.list().get(0);

    return count >= 1 ? true : false;
    }

    que en mi caso lo tengo asi, pero creo que es lo mismo:
    @Override
    public boolean isOauthClientDetailsDisponible(String clientId) {
    Assert.notNull(clientId);
    Criteria criteria = createEntityCriteria().add(Restrictions.eq(“clientId”, clientId));
    Long count = (Long) criteria.list().get(0);
    return count >= 1 ? true : false;

    }

    El resultado del list se castea como “Long”, lo que hice fue ponerlo en “int” y me resultó este error: (es casi lo mismo solo que ahora cambia a Integer)
    {
    “error”: “unauthorized”,
    “error_description”: “com.golwin.application.model.OauthClientDetails cannot be cast to java.lang.Integer”
    }

    A que se debería esto?
    Agradecería mucho podrías ayudarme nuevamente. Gracias

    1. Saludos Christian,

      no se exactamente como tendrás tu logica pero el error es claro estás tratando de castear un object com.golwin.application.model.OauthClientDetails a java.lang.Integer, y por eso te salta la excepción, por lo que puedo observar, como te dije sin conocer tu logica tu criteria no está devolviendo un count(*) como lo hago yo sino un objeto OauthClientDetail, lo que yo intentaría sería contar el # de objetos con el criteria y devolver ese count no el OauthClientDetails..

      1. Gracias por tu ayuda, ya pude obtener el token, cambie algo en el código y funcionó. Gracias. Que tengas un excelente dia.
        Si surge cualquier inconveniente, estaré regresando por tu valiosa ayuda (espero no incomodar)

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s