Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

Enviando senha em claro para a autenticação

5 respostas

Oi Marcson,

A senha do usuário sempre será enviada em texto aberto mesmo(tanto pelo postman quanto pelo frontend/mobile). Para evitar problemas de segurança nesse cenário, entra a utilização do HTTPS.

Mas independente disso, não deveria mudar nada no código do backend, mesmo com você utilizando outro algoritmo de hash, como o SHA1.

Pode postar suas classes e o problema que está acontecendo?

OI Rodrigo! vou tentar colocar todas que fazem parte da autenticação, seguem abaixo minhas classes:

package br.com.findvet.service;
import java.util.Date;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import br.com.findvet.modelo.Pessoa;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

@Service
public class TokenService {
@Value("${findvet.jwt.expiration}")
private String expiration;
@Value("${findvet.jwt.secret}")
private String secret;

public String gerarToken(Authentication authentication) {
Pessoa logado = (Pessoa) authentication.getPrincipal();
Date hoje = new Date();
Date dataExpiracao = new Date(hoje.getTime() + Long.parseLong(expiration));
return Jwts.builder()
.setIssuer("API DA FINDVET - SISTEMA DE CONSULTA VETERINÁRIA")
.setSubject(logado.getId().toString())
.setIssuedAt(hoje)
.setExpiration(dataExpiracao)
.signWith(SignatureAlgorithm.HS256, secret)
.compact();
}

public boolean isTokenValido(String token) {
try {
Jwts.parser().setSigningKey(this.secret).parseClaimsJws(token);
return true;
} catch (Exception e) {
return false;
}
}

public Long getIdPessoa(String token) {
Claims claims = Jwts.parser().setSigningKey(this.secret).parseClaimsJws(token).getBody();
return Long.parseLong(claims.getSubject());
}

}
------------------------------------
package br.com.findvet.security;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import br.com.findvet.modelo.Pessoa;
import br.com.findvet.repository.PessoaRepository;
import br.com.findvet.service.TokenService;

public class AutenticacaoViaTokenFilter extends OncePerRequestFilter {

private TokenService tokenService;
private PessoaRepository repository;

public AutenticacaoViaTokenFilter(TokenService tokenService, PessoaRepository repository) {
this.tokenService = tokenService;
this.repository = repository;
}

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {

String token = recuperarToken(request);
boolean valido = tokenService.isTokenValido(token);
if (valido) {
autenticarCliente(token);
}

filterChain.doFilter(request, response);
}

private void autenticarCliente(String token) {
Long idPessoa = tokenService.getIdPessoa(token);
Pessoa pessoa = repository.findById(idPessoa).get();
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(pessoa, null, pessoa.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
}

private String recuperarToken(HttpServletRequest request) {
String token = request.getHeader("Authorization");
if (token == null || token.isEmpty() || !token.startsWith("Bearer ")) {
return null;
}

return token.substring(7, token.length());
}


}
-----------------------------------------------
package br.com.findvet.security;

import java.math.BigInteger;
import java.security.MessageDigest;

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

public class EncodedSha1 implements PasswordEncoder{

@Override
public String encode(CharSequence rawPassword) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
       digest.reset();
       digest.update(((String) rawPassword).getBytes("utf8"));
       String sha1 = String.format("%040x", new BigInteger(1, digest.digest()));
       return sha1;
} catch (Exception e){
e.printStackTrace();
return "Erro ao criptografar";
}

}

@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
if(encodedPassword.equals(rawPassword)){    
return true;
}
return false;
}

}

Rodrigo aqui seguem as outras, retirei dto , form e controller que é padrão:


package br.com.findvet.service;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import br.com.findvet.modelo.Pessoa;
import br.com.findvet.repository.PessoaRepository;

@Service
public class AutenticacaoService implements UserDetailsService {

@Autowired
private PessoaRepository repository;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Pessoa> pessoa = repository.findByEmail(username);
if (pessoa.isPresent()) {
return pessoa.get();
}
throw new UsernameNotFoundException("Dados inválidos!");
}
}
---------------------------------------------
package br.com.findvet.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
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.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import br.com.findvet.repository.PessoaRepository;
import br.com.findvet.service.AutenticacaoService;
import br.com.findvet.service.TokenService;

@EnableWebSecurity
@Configuration
public class ConfiguracoesDeSeguranca extends WebSecurityConfigurerAdapter {

@Autowired
private AutenticacaoService autenticacaoService;

@Autowired
private TokenService tokenService;

@Autowired
private PessoaRepository pessoaRepository;

@Override
@Bean
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
//Configuracoes de autenticacao
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(autenticacaoService).passwordEncoder(new EncodedSha1());
}
//Configuracoes de autorizacao
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(HttpMethod.POST,"/clientes/*").permitAll()
.antMatchers(HttpMethod.POST,"/parceiros/*").permitAll()
.antMatchers(HttpMethod.POST, "/auth").permitAll()
.anyRequest().authenticated()
.and().csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().addFilterBefore(new AutenticacaoViaTokenFilter(tokenService, pessoaRepository), UsernamePasswordAuthenticationFilter.class);
}
//Configuracoes de recursos estaticos(js, css, imagens, etc.)
@Override
public void configure(WebSecurity web) throws Exception {
}
}
solução!

Acho que o problema está na sua classe EncodedSha1, no método matches:

@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
    if(encodedPassword.equals(rawPassword)) {    
        return true;
    }
    return false;
}

Esse método deve comparar se a senha em texto aberto(parâmetro rawPassword) é a senha que gerou a versão encoded(parâmetro encodedPassword), mas no seu método você compara se os parâmetros são iguais, mas nunca serão. O correto deveria ser algo assim:

public boolean matches(CharSequence rawPassword, String encodedPassword) {
    String encoded = this.encode(rawPassword);
    if(encodedPassword.equals(encoded)) {
        return true;
    }
    return false;
}

Rodrigo obrigado pela ajuda o problema era no método matches mesmo.