WebSecurityConfig.java
/**
* TFG 75.678 - TFG Desarrollo web 2020 e-Learning for Schools
* Copyright (C) 2020 Eduardo Rodriguez Carro
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.uoc.tfg.sel.config;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder.BCryptVersion;
import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.uoc.tfg.sel.security.JwtAuthenticationEntryPoint;
import org.uoc.tfg.sel.security.JwtRequestFilter;
import org.uoc.tfg.sel.security.JwtUserDetailsService;
/**
* Configuracion de seguridad
*
* Se usa NoOpPasswordEncoder como metodo alternativo bajo el
* DelegatingPasswordEncoder para poder establecer las claves iniciales .
*
* @author Eduardo Rodriguez Carro
*/
@Profile("!test")
@SuppressWarnings("deprecation")
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
/** The cors origin. */
@Value("${adpcus.cors.origin:*}")
private List<String> corsOrigin;
/** The cors allowed methods. */
@Value("${adpcus.cors.allowed.methods: GET,POST,DELETE,PUT}")
private List<String> corsAllowedMethods;
/** The cors allowed headers. */
@Value("${adpcus.cors.allowed.headers:Authorization}")
private List<String> corsAllowedHeaders;
/** The jwt authentication entry point. */
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
/** The user details service. */
@Autowired
private JwtUserDetailsService userDetailsService;
/** The jwt request filter. */
@Autowired
private JwtRequestFilter jwtRequestFilter;
/**
* Configuracion del autenticador.
*
* @param auth the auth
* @throws Exception the exception
*/
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// anadimos nuestro servicio para obtener los datos del usuario asi como el servicio de cifrado de la password
auth.eraseCredentials(true);
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
/**
* Objeto para el cifrado de las passwords.
*
* @return the password encoder
*/
@Bean
public PasswordEncoder passwordEncoder() {
Map<String,PasswordEncoder> allowedEncoders = new HashMap<>();
allowedEncoders.put("np", NoOpPasswordEncoder.getInstance());
allowedEncoders.put("bc", new BCryptPasswordEncoder(BCryptVersion.$2Y,10));
return new DelegatingPasswordEncoder("bc",allowedEncoders);
}
/**
* Autenticador.
*
* @return the authentication manager
* @throws Exception the exception
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* Cors configurer.
*
* @return the web mvc configurer
*/
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("PUT", "DELETE","GET","POST");
}
};
}
/**
* Configurador de la seguridad HTTP.
*
* @param httpSecurity the http security
* @throws Exception the exception
*/
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
// No es necesario CSRF
httpSecurity.cors().and().csrf().disable()
// el API De login no requiere estar autenticado
.authorizeRequests().antMatchers("/auth/login").permitAll().
// El resto de peticiones requieren estar autenticado y se validaran con la seguridad por anotaciones
anyRequest().authenticated().and().
// Establecemos el punto de error cuando no se ha autenticado a una pagina de error
// No implementamos en este lado un formularo de login
exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
// Establecemos el servidor como stateless, para no guardar datos de sesion en memoria ni cookies
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Incroporamos el fitro de peticiones que se encargara de validar el usuario con el token JWT
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}