Java + Spring + Thymeleaf + Spring Security [RESOLVIDO]

9 respostas Resolvido
springjava
E

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/

9 Respostas

D

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

E

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();
}
E

Ninguém?

J

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

E

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.

J

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";
    }

}
E

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á…

E

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?

E
Solucao aceita

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

Criado 19 de março de 2021
Ultima resposta 1 de abr. de 2021
Respostas 9
Participantes 3