quinta-feira, 30 de julho de 2015

Configurando Spring Security 4 com JSF 2.2 e CDI 1.1

Hoje irei mostrar como configurar o Spring Security 4 em aplicações que utilizam JSF e CDI. Assumirei que o CDI que já está previamente configurado.

Neste projeto estão sendo utilizados:
  • CDI 1.1
  • JSF 2.2
  • Spring Security 4.0.1
  • Maven
  • Primefaces 5.2
Toda a configuração será feita de forma programática, dispensando qualquer arquivo xml.

Vamos ao pom.xml

        
            org.springframework
            spring-framework-bom
            4.0.1.RELEASE
            pom
            compile
         
        
        
          
            org.springframework.security  
            spring-security-web  
            4.0.1.RELEASE  
         
         
        
          
            org.springframework.security  
            spring-security-config  
            4.0.1.RELEASE  
        

                
        
            commons-logging
            commons-logging
            1.2
        
A classe responsável por iniciar o serviço de segurança do Spring:
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

    public SecurityWebApplicationInitializer() {
        super(SecurityConfig.class);
    }
}

Vamos criar a classe que conterá boa parte das implementações de restrições de páginas, a SecurityConfig:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("zezinho").password("123456").roles("COMUM");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();

        http.exceptionHandling().and().authorizeRequests().and()
                .exceptionHandling().accessDeniedPage("/acesso-negado.jsf").and().authorizeRequests()
                .antMatchers("/javax.faces.resource/**").permitAll()
                .and().authorizeRequests()
                .antMatchers("/cadastro-usuarios.jsf", "/cadastro-empresas.jsf").hasRole("ADMINISTRADOR")
                .anyRequest().authenticated()
                .and().logout().logoutSuccessUrl("/login.jsf?logout").permitAll()
                .and().formLogin() //.loginPage("/login.jsf") Para utilizar a própria página de login
                .failureUrl("/login.jsf?erro").permitAll();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/**");
    }
}

Pronto ! Agora basta rodar a aplicação que a primeira página a ser exibida será um formulário de login do próprio Spring. Caso você tente acessar as URL's que possuem hasRole("ADMINISTRADOR"), o Spring irá redirecionar para acesso-negado.jsf, e é claro, nenhum usuário pode acessar qualquer página da aplicação sem estar devidamente autenticado.

A linha .antMatchers("/javax.faces.resource/**").permitAll(), se refere a liberar os recursos de tela para usuário, como CSS, JavaScript e imagens. O método public void configure(WebSecurity web), também libera o acesso para endereços /resources/** nos GET's do navegador. Eu particularmente tive alguns problemas em conseguir liberar corretamente, passei por alguns erros muito estranhos que envolviam a pasta resources. Deixarei o Post que criei no GUJ ao final. 

Página de Login Personalizada e Logout

A página de login deve ser da seguinte forma:
      
        
        

           
            
           
           

        
        

         

         
         

         
                
Usuário ou senha inválidos.
Botão para Logout.
Sim
Os inputs do formulário de login devem possuir exatamente os ID's username e password, são por esses campos que o Spring faz associação das informações passadas no momento do login.

Foram usadas classes de CSS do primefaces pois ele é uma dependência do projeto.

A autenticação desta configuração ainda é feita utilizando o método inMemoryAuthentication(), em outro post iremos configurar com autenticação via banco de dados.

Fontes:

Documentação do Spring Security
http://docs.spring.io/spring-security/site/docs/4.0.3.CI-SNAPSHOT/reference/htmlsingle/

Documentação de Setup inicial do SpringSecurity:
http://docs.spring.io/spring-security/site/docs/current/guides/html5//index.html

Documentação de migração do Spring 3x para o 4x:
http://docs.spring.io/spring-security/site/migrate/current/3-to-4/html5/migrate-3-to-4-jc.html

Dez utilidades do Spring Security:
http://imasters.com.br/linguagens/java/dez-coisas-que-voce-pode-fazer-com-o-spring-security/

Minha pergunta no GUJ sobre o erro que tive com o Spring:
http://www.guj.com.br/43567-jsf-2--cdi-11--springsecurity-4-custom-login-form-nao-redireciona-para-pagina-correta

4 comentários :

  1. Você poderia disponibilizar o código fonte do projeto funcionando no github. ;)

    ResponderExcluir
  2. Você poderia disponibilizar o código fonte do projeto funcionando no github

    ResponderExcluir
  3. Você poderia disponibilizar o código fonte do projeto funcionando no github

    ResponderExcluir