Problemas ao fazer consultas em API java rest com Angular

estou tentando implementar uma api usando spring boot e spring security, consegui fazer a autenticação de acesso co login e senha, no entanto, apos conseguir acesso não consigo fazer a busca por dados no banco, o navegador alega acesso negado, alguém poderia me ajudar com esse problema??

back:
git clone https://alexsandroandrade@bitbucket.org/alexsandroandrade/api-spring-restful.git

front:
git clone https://alexsandroandrade@bitbucket.org/alexsandroandrade/curso-angular.git

erro dado no console do navegador

O token está indo corretamente na requisição?

1 curtida

boa noite Lucas! sim, o angular esta recebendo o token normalmente, o login esta ocorrendo normalmente

Blz, mas ao consultar, o token também está sendo enviado na requisição GET (header Authorization)?

1 curtida

bom dia Lucas! eu acabei observando que na minha classe
br.com.alexdeveloper.springrestapi.security.JWTTokenAutenticacaoService

dentro do método de pegar a autenticação, getAuthentication o token esta vindo nulo, na hora que faço a minha consulta depois de ter logado, não consegui entender o porque disso esta ocorrendo, consegue me ajudar?

Como vc está enviando o token pelo frontend? (copie e cole o código, evite mandar a imagem do código)

1 curtida

Lucas, como eu ainda estou estudando sobre o assunto, acabo tendo alguns problemas no entendimento. mas acredito que faço esse envio no método addAuthentication. dentro da classe JWTTokenAutenticacaoService

@Service
@Component
public class JWTTokenAutenticacaoService {

// Senha única para compor a autenticação e ajudar na segurança
private static final String SECRET = "SenhaExtremamenteSecreta";

// Prefixo padrão de Token
private static final String TOKEN_PREFIX = "Bearer";

private static final String HEADER_STRING = "Authorization";

// Gerando token de autenticação e adicionando ao cabeçalho e resposta Http
/*Gerando token de autenticado e adiconando ao cabeçalho e resposta Http*/
public void addAuthentication(HttpServletResponse response , String username) throws IOException {
	liberacaoCors(response);
	/*Montagem do Token*/
	String JWT = Jwts.builder() /*Chama o gerador de Token*/
			        .setSubject(username) /*Adicona o usuario*/				        
			        .signWith(SignatureAlgorithm.HS512, SECRET).compact(); /*Compactação e algoritmos de geração de senha*/
	
	/*Junta token com o prefixo*/
	String token = JWT; /*Bearer 87878we8we787w8e78w78e78w7e87w*/
	
	/*Adiciona no cabeçalho http*/
	response.addHeader(HEADER_STRING, token); /*Authorization: Bearer 87878we8we787w8e78w78e78w7e87w*/
	
	/*Liberando resposta para porta diferente do projeto Angular*/
	
	

	
	/*Escreve token como responsta no corpo http*/
	response.getWriter().write("{\"Authorization\": \""+token+"\"}");
	
}

// Retorna o usuário validado com token ou caso não seja válido retorna null
public Authentication getAuthentication(HttpServletRequest request, HttpServletResponse response) {
	
	
	liberacaoCors(response);
	// Pega o token enviado no cabeçalho Http
	String token = request.getHeader(HEADER_STRING);
	
	if (token != null) {			
		// Faz validação do Token do usuário na requisição
		String user = Jwts.parser()
				.setSigningKey(SECRET)
				.parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
				.getBody()
				.getSubject();	
		
		if (user != null) {					
			Usuario usuario = ApplicationContextLoad
					.getApplicationContext()
					.getBean(UsuarioRepository.class)
					.findUserByLogin(user);
			
			if (usuario != null) {
				return new UsernamePasswordAuthenticationToken(
						usuario.getLogin(), 
						usuario.getSenha(), 
						usuario.getAuthorities());
			}
		}
	}	
	
	return null;
}

private void liberacaoCors(HttpServletResponse response) {
	if (response.getHeader("Access-Control-Allow-Origin") == null) {
		response.addHeader("Access-Control-Allow-Origin", "*");
	}
	
	if (response.getHeader("Access-Control-Allow-Headers") == null) {
		response.addHeader("Access-Control-Allow-Headers", "*");
	}
	
	if (response.getHeader("Access-Control-Request-Headers") == null) {
		response.addHeader("Access-Control-Request-Headers", "*");
	}
}

}

Veja bem. Ao autenticar, quando o token for gerado, ele deve ser enviado ao cliente (frontend). Com o token em mãos, o frontend deve armazená-lo em um cookie ou localstorage do navegador, para que, em novas requisições, o frontend envie esse token utilizando o header Authorization.

1 curtida

entendi Lucas! nesse momento eu estou recebendo essa autenticação no meu front, pois com ela é possivel eu fazer o login, nesse trecho do código ocorre exatamente o que vc esta dizendo, coloquei um debugger no codigo do front e abri o console pra vc ver como estou conseguindo capturar a autenticação, a questao e que depois de conseguir logar eu nao consigo buscar uma lista de dados no meu banco, pois ele continua alegando erro de autenticação.

armazenando o token no storage no front

login(usuario){

console.info(JSON.stringify(usuario));

return this.http.post(AppConstants.baseLogin, JSON.stringify(usuario)).subscribe(data => {

  debugger;

  var token = JSON.parse(JSON.stringify(data)).Authorization;

  localStorage.setItem("token", token);

  console.log("token " + localStorage.getItem("token"));

  this.router.navigate(['home']);

},

  error => {

    console.error("Erro ao fazer login");

    alert("Acesso negado");

  }

);

}

console

Após o login, a rota é enviada para home. O componente dessa rota faz alguma requisição http? Se sim, como que vc está enviado o token nessa requisição?

1 curtida

dentro da home eu faço uma requisição GET usando a url http://localhost:4200/usuariosList

TS que é chamado com essa url

@Component({

  selector: 'app-usuario',

  templateUrl: './usuario.component.html',

  styleUrls: ['./usuario.component.css']

})

export class UsuarioComponent implements OnInit {

  usuariosList: Observable<Usuario[]>;

  constructor(private usuarioService: UsuarioService) {

   }

  ngOnInit() {

    this.usuarioService.getUsuariosList().subscribe(data => {

      this.usuariosList = data;

    });

  }

}

essa URL chama o service usuarioService

@Injectable({

  providedIn: 'root'

})

export class LoginServiceService {

  constructor(private http: HttpClient, private router : Router) { }

  login(usuario){

    console.info(JSON.stringify(usuario));

    return this.http.post(AppConstants.baseLogin, JSON.stringify(usuario)).subscribe(data => {

      debugger;

      var token = JSON.parse(JSON.stringify(data)).Authorization;

      localStorage.setItem("token", token);

      console.log("token " + localStorage.getItem("token"));

      this.router.navigate(['home']);

    },

      error => {

        console.error("Erro ao fazer login");

        alert("Acesso negado");

      }

    );

  }

}

é nesse momento que o console me da o erro abaixo

em nenhum momento eu envio de novo essa autenticação, como eu deveria fazer isso?

rotas

export const appRouters: Routes = [

  {path : 'home', component: HomeComponent},

  {path: 'login', component: LoginComponent},

  {path: '', component: LoginComponent},

  {path: 'usuariosList', component: UsuarioComponent}

];

Tu pode criar um http interceptor: https://medium.com/@ryanchenkie_40935/angular-authentication-using-the-http-client-and-http-interceptors-2f9d1540eb8

1 curtida

eu ja tenho esse interceptor implementada, talvez ele nao esteja funcionando corretamente

import { Injectable, NgModule } from '@angular/core';
import { HttpInterceptor, HTTP_INTERCEPTORS, HttpErrorResponse, HttpEvent, HttpResponse } from '@angular/common/http';
import { throwError } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';

@Injectable()
export class HeaderInterceptorService implements HttpInterceptor {
	
	intercept(req: import("@angular/common/http").HttpRequest<any>, 
		next: import("@angular/common/http").HttpHandler): import("rxjs").Observable<import("@angular/common/http").HttpEvent<any>> {
	
		if (localStorage.getItem('token') !== null) {
			const token = localStorage.getItem('token');
			const tokenRequest = req.clone({
				headers: req.headers.set('Authorization', token)
			});
			
			return next.handle(tokenRequest).pipe(tap((event: HttpEvent<any>) => {
				if (event instanceof HttpResponse && (event.status === 200 || event.status === 201)) {
					console.info('Sucesso na operação');
				}
			}), catchError(this.processaError));
		} else {
			return next.handle(req).pipe(catchError(this.processaError));
		}
	}
	
	constructor() { }
	
	processaError(error: HttpErrorResponse) {
		let errorMessage = 'Erro desconhecido';
		
		if (error.error instanceof ErrorEvent) {
			console.error(error.error);
			errorMessage = 'Error: ' + error.error.error;
		} else {
			errorMessage = 'Código: ' + error.error.code + '\nMensagem: ' + error.error.error;
		}
		
		window.alert(errorMessage)
		return throwError(errorMessage);
	}
}
@NgModule({
	providers: [{
		provide: HTTP_INTERCEPTORS,
		useClass: HeaderInterceptorService,
		multi: true,
	},
	],
})
export class HttpInterceptorModule {

}

Coloque um debugger nele para ver se ele está sendo chamado. Para checar se não eh problema no backend, tente fazer a requisição pelo postman (ou qualquer outro) passando o token.

1 curtida

coloquei, em nenhum momento o interceptor esta sendo chamado. no postman os dados chegam corretamente

O HttpInterceptorModule foi adicionado ao módulo principal app.module ? Vc também pode tentar adicionar o interceptor diretamente no app.module para testar.

1 curtida

@Lucas_Camara, o HttpInterceptorModule não estava adicionado do app.module acabei de fazer isso e obtive outro erro, nao consegui entender do que se trata.

import { HeaderInterceptorService } from './service/header-interceptor-service.service';

import { RouterModule, Routes } from '@angular/router';

import { BrowserModule } from '@angular/platform-browser';

import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';

import { AppComponent } from './app.component';

import { FormsModule } from '@angular/forms';

import {HttpClientModule} from '@angular/common/http';

import { HomeComponent } from './home/home.component';

import {ModuleWithProviders} from '@angular/compiler/src/core';

import { LoginComponent } from './login/login.component';

import { UsuarioComponent } from './componente/usuario/usuario.component';

export const appRouters: Routes = [

  {path : 'home', component: HomeComponent},

  {path: 'login', component: LoginComponent},

  {path: '', component: LoginComponent},

  {path: 'usuariosList', component: UsuarioComponent}

];

export const routes: ModuleWithProviders = RouterModule.forRoot(appRouters);

@NgModule({

  declarations: [

    AppComponent,

    HomeComponent,

    LoginComponent,

    UsuarioComponent,

  ],

  imports: [

    BrowserModule,

    AppRoutingModule,

    FormsModule,

    HttpClientModule,

    routes,

    HeaderInterceptorService

  ],

  providers: [],

  bootstrap: [AppComponent]

})

export class AppModule { }

esse é o erro que da no console

Você não precisa colocar o HeaderInterceptorService como imports no app.module. Você soh precisa adicionar:

providers: [{
    provide: HTTP_INTERCEPTORS,
    useClass: HeaderInterceptorService,
    multi: true
}]

no app.module, e testar.


O estranho eh que o HttpClientModule está importado no app.module. Isso deveria funcionar. Como está o seu HttpClientModule?