Java + Spring + Thymeleaf + Spring Security [RESOLVIDO]

Pessoal, estou iniciando em Spring. E estou gostando muito.

Mais estou com um probleminha, estou tentando fazer com o que o spring security pare de exibir a tela padrão de login dele, e mostre uma tela customizada. Só que o que está acontecendo, mesmo criando um WebSecurityConfig, botando a anotação @Configuration, colocando extends WebSecurityConfigurerAdapter, e fazer um Override no método de configuração. O Spring não faz esse Override, exibe a tela de de login padrão do Spring para todas as solicitação, ou seja, não deixa nem eu abrir uma uma tela de cadastro de usuário.

E mesmo que eu cadastre um usuário na mão no banco de dados, ele não pega o usuário do banco, só funciona com o usuário padrão que o Spring cria.

@Override
protected void configure(HttpSecurity http) throws Exception {

	http.authorizeRequests()
		/*DETERMINA QUE PARA REALIZAR ESSA REQUEST PRECISA TER UMA DAS PERMISSÕES ABAIXO
	 	* EXEMPLO DA URL: http://localhost:8095/usuario/novoCadastro
	 	* VEJA QUE EM UM ITEM("hasRole('ADMIN')) NÃO ESTOU PASSANDO O PREFIXO ROLE_, ESSE PREFIXO NÃO É OBRIGATÓRIO 
	 	* QUANDO USAMOS o hasRole*/
		.antMatchers("/usuario/novoCadastro").access("hasRole('ADMIN') or hasRole('ROLE_CADASTROUSUARIO')")
		/*DETERMINA QUE PARA REALIZAR ESSA REQUEST PRECISA TER UMA DAS PERMISSÕES ABAIXO
		 * EXEMPLO DA URL: http://localhost:8095/usuario/consultar */
		.antMatchers("/usuario/consultar").access("hasRole('ADMIN') or hasRole('CONSULTAUSUARIO')")
		 /*DETERMINA QUE PARA ACESSAR A PÁGINA INICIAL DA APLICAÇÃO PRECISA ESTÁ AUTENTICADO*/
		.antMatchers("/home").authenticated()
		.anyRequest().authenticated()			
		.and()			
			.formLogin()
			 /*INFORMANDO O CAMINHO DA PÁGINA DE LOGIN, E SE O LOGIN FOR EFETUADO COM SUCESSO
			  *O USUÁRIO DEVE SER REDIRECIONADO PARA /home(http://localhost:8095/home)*/
			.loginPage("/").defaultSuccessUrl("/home",true)
			.permitAll() /*AQUI ESTAMOS INFORMANDO QUE TODOS TEM ACESSO A PÁGINA DE LOGIN*/
		.and()
		     /*AQUI ESTAMOS INFORMANDO QUE QUANDO FOR REDIRECIONADO PARA  O LINK http://localhost:8095/logout
		      *O USUÁRIO DEVE TER SUA SESSÃO FINALIZADA E REDIRECIONADO PARA A PÁGINA DE LOGIN */
			.logout()
			.logoutSuccessUrl("/")
			.logoutUrl("/logout") 
			.permitAll();


	/*PÁGINA COM A MENSAGEM DE ACESSO NEGADO
	 *QUANDO O USUÁRIO NÃO TER UMA DETERMINADA PERMISSÃO DE ACESSO AO SISTEMA ELE VAI SER REDIRECIONADO
	 *PARA A URL ABAIXO */
	http.exceptionHandling().accessDeniedPage("/acessoNegado");

	/*AQUI ESTOU INFORMANDO QUE QUALQUER REQUEST TEM ACESSO AO DIRETÓRIO src/main/resources */
	http.authorizeRequests().antMatchers("/resources/**").permitAll().anyRequest().permitAll();




}

Estou tentando seguir esse tutorial: http://www.ciceroednilson.com.br/criando-uma-aplicacao-web-com-spring-boot-thymeleaf-material-designer-lite-e-oracle-parte-4-configurando-o-spring-security/

Me desculpa, mas esses comentários não te incomodam?

1 curtida

Como falei estou seguindo o tutorial, mais eu tiro os comentários:

@Override
protected void configure(HttpSecurity http) throws Exception {
	http.authorizeRequests()
		.antMatchers("/usuario/novoCadastro").access("hasRole('ADMIN') or hasRole('ROLE_CADASTROUSUARIO')")
		.antMatchers("/usuario/consultar").access("hasRole('ADMIN') or hasRole('CONSULTAUSUARIO')")
		.antMatchers("/home").authenticated()
		.anyRequest().authenticated()			
		.and()			
			.formLogin()
			.loginPage("/").defaultSuccessUrl("/home",true)
			.permitAll()
		.and()
			.logout()
			.logoutSuccessUrl("/")
			.logoutUrl("/logout") 
			.permitAll();


	http.exceptionHandling().accessDeniedPage("/acessoNegado");

	http.authorizeRequests().antMatchers("/resources/**").permitAll().anyRequest().permitAll();
}

Ninguém?

Como está o controller que retorna as páginas customizadas?

Gradle.build

plugins {
	id 'org.springframework.boot' version '2.4.2'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}
repositories {
	mavenCentral()
}
dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-validation'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter-security'
	implementation 'org.codehaus.groovy:groovy'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	runtimeOnly 'org.postgresql:postgresql'
	annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	compile 'com.github.zhanhb:thymeleaf-layout-dialect:2.5.2'
}
test {
	useJUnitPlatform()
}

WebSecurityConfig

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .formLogin(form -> form
                    .loginPage("/login")
                    .permitAll()
            )
            .logout(logout -> logout.logoutUrl("/logout"));
}

@Bean
@Override
public UserDetailsService userDetailsService() {
    UserDetails user =
            User.withDefaultPasswordEncoder()
                    .username("joao")
                    .password("joao")
                    .roles("ADM")
                    .build();

    return new InMemoryUserDetailsManager(user);
}

}

HomeController

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HomeController {

@GetMapping("/login")
public String login() {
    return "login";
}

}

Estou tentando fazer o simples, a eu não coloquei aqui mais criei um login.html na templates.

Estranho! :confused:

A implementação que eu tenho é bem parecida com a sua, porém pra mim funciona perfeitamente!

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
	    http
		    .formLogin()
                .loginPage("/login")
		.and()
		    .authorizeRequests()
		        .antMatchers("/oauth/**")
                    .authenticated()
		.and()
			.csrf()
                .disable()
			.cors()
		.and()
			.oauth2ResourceServer()
				.jwt()
				.jwtAuthenticationConverter(jwtAuthenticationConverter());
	}

    //Demais métodos da classe omitidos
}

Única diferença é que eu separei as páginas em um diretório de nome pages dentro de templates.

@Controller
public class SecurityController {
    
    @GetMapping("/login")
    public String login() {
        return "pages/login";
    }

}

Muito estranho.

Eu fui lá no Spring Inicializer, botei Spring MVC, Boot e Security só…

Fui no Intellij, inicializei o projeto, rodou certinho, fiz a configuração básica, gerou o a senha para o usuário user como padrão.

Mais aí eu criei uma tela de login, só para ver se pega a tela de login customizada, e nada, mesmo coisa.

Tirei a tela de login, deixei a padrão, e setei o usuário inmemory, e não funciona também, cria sempre aquela senha padrão do Spring…

Será que não tem nenhum configuração para fazer no application.properties, sei lá…

Vou por mais informações…
Como falei na resposta anterior, estou com um projeto do zero, só com Spring MVC+ Sprgin Boot + Spring Security

Estrutura do projeto

WebSecurityConfig

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
                .anyRequest().authenticated()
            .and()
            .httpBasic();
}

@Bean
public UserDetailsService users() {
    UserDetails user = User.builder()
            .username("user")
            .password("user")
            .roles("USER")
            .build();
    return new InMemoryUserDetailsManager(user);
}

}

application.properties

main

Ele não faz override em lugar nenhum do security, eu botei o http basic e não vai(aparece a tela abaixo), e deveria pedir login via alert pelos tutoriais que eu vi.

Ou seja, o Override não está funcionando, e eu não sei o porque.
Alguém consegue me dar uma luz?

Resolvido.

O pacote config estava em lugar errado, tem que estar no mesmo lugar da main, ou tenho que usar uma annotation de nome @ComponenteScan

A solução achei nesse post: https://stackoverflow.com/questions/38072517/unable-to-override-spring-boots-default-security-configuration