CORS no spring - solucionado

Tenho este CORS em java

package br.com.ghsistemas.usuarios.filter;

import lombok.extern.apachecommons.CommonsLog;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE;

@Component
@Order(HIGHEST_PRECEDENCE)
@CommonsLog
public class SmpleCORSFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("Sistema de usuários | SmpleCORSFilter início");
    }

    @Override
    public void doFilter(ServletRequest req,
                         ServletResponse resp,
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization, Cotent-Type, Authorization");
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, resp);
        }
    }

    @Override
    public void destroy() {
    }
}

Porem não consigo acessar nenhum endpoint.

No angular:

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

import { HttpClient, HttpHeaders } from '@angular/common/http';

import { User } from '../model/user.model';

import { USUARIOS_API } from './usuarios.api';

@Injectable({

  providedIn: 'root'

})

export class UserService {

  constructor(private http: HttpClient) {}

  public getHeaders(): HttpHeaders {

    const headers =  new HttpHeaders({

        'Content-Type': 'application/json',

        'Access-Control-Allow-Origin': '*',

        'Access-Control-Allow-Methods': 'GET, POST, OPTIONS, PUT, PATCH, DELETE'

    });

    return headers;

  }

  login(user: User) {

     return this.http.post(`${USUARIOS_API}/api/auth`, user, {headers: this.getHeaders()});

  }

}

O que pode ser ?

Geralmente eu uso outra implementação de CORS, o exemplo abaixo tem as configurações mínimas.

import javax.servlet.Filter;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.ShallowEtagHeaderFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

	@Override
	public void addCorsMappings(CorsRegistry registry) {
		registry.addMapping("/**")
			.allowedMethods("*");
	}
}

Criei esta classe idêntica e e não funcionou.

Então acredito que o problema não deve estar na implementação da classe CORS, alguma outra coisa na sua aplicação deve estar sobrepondo a implementação que trata isso.

Também acredito que não. Porque todas implementações do CORS que vejo estão idênticas.

Mas o que por exemplo ? Tem alguma ideia ?

É um projeto POM, que tem Module.

Esta usando Spring Security? se sim tem que configurar lá também.

Estou usando Spring Security sim.

Algo assim

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

public class ExampleWebSecurity extends WebSecurityConfigurerAdapter
{
    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
        http.cors().configurationSource(corsConfiguration());
    }

    private CorsConfigurationSource corsConfiguration(){
        var source = new UrlBasedCorsConfigurationSource();
        var config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("DELETE");
        source.registerCorsConfiguration("/**", config);
        return source;
    }
}

Se tudo der errado use a anotação @CrossOrigin(pesquise sobre ela) no método, para realizar alguns testes, se funcionar com a anotação falta configuração em algum lugar.

Parecido com seu, código copiado da internet que funciona em um projeto aqui:

import java.io.IOException;
import java.util.TimeZone;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;

@Component
public class SimpleCORSFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {    	
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, content-type, Accept");
        response.setHeader("Access-Control-Expose-Headers", "Location");
        chain.doFilter(req, res);
    }

    @Override
    public void init(FilterConfig filterConfig) {}

    @Override
    public void destroy() {}
}

Não entra no server
@javaflex

Access to XMLHttpRequest at 'localhost:8090/api/auth' from origin 'http://localhost:4200' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
zone.js:3243 POST localhost:8090/api/auth net::ERR_FAILED

Sempre dá este erro no console do navegador.

Mesmo erro falado anteriormente.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>br.com.ghsistemas.usuarios</groupId>
    <artifactId>usuarios</artifactId>
    <version>0.0.1</version>
    <packaging>pom</packaging>

    <modules>
        <module>core</module>
        <module>rest</module>
        <module>utilitario</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.7.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>1.8</java.version>
        <java.encoding>UTF-8</java.encoding>
        <maven.build.timestamp.format>dd/MM/yyyy HH:mm:ss</maven.build.timestamp.format>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <project.build.sourceEncoding>${java.encoding}</project.build.sourceEncoding>
        <project.reporting.outputEncoding>${java.encoding}</project.reporting.outputEncoding>

        <principal.ghsistemas.version>0.0.1-SNAPSHOT</principal.ghsistemas.version>

        <project.main.basedir>${project.basedir}</project.main.basedir>
        <jjwt.version>0.9.1</jjwt.version>
        <passay.version>1.4.0</passay.version>
        <collections4.version>4.2</collections4.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
    </dependencies>
</project>

Criei outra aplicação simples.

Com este Cors e não adiantou. O erro continua:

package br.com.ghsistemas.auth;

import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class Cors implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest req,
                         ServletResponse resp,
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, content-type, Accept");
        response.setHeader("Access-Control-Expose-Headers", "Location");
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, resp);
        }
    }

    @Override
    public void destroy() {
    }
}

Rest simples:

package br.com.ghsistemas.auth.rest;

import org.springframework.web.bind.annotation.*;

import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE;

@RestController
@RequestMapping("/sistemas")
@CrossOrigin(origins = "*")
public class SistemasRestController {

    @CrossOrigin(origins = "*")
    @PostMapping(value = "/pesquisar", produces = APPLICATION_JSON_UTF8_VALUE)
    //@PreAuthorize("hasAnyRole('ROLE_ADMINISTRADOR')")
    public void buscarDicionarioSenhaPaginacao() {
        Integer a = 1;
        a++;
    }
}

pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>br.com.ghsistemas.auth</groupId>
    <artifactId>auth</artifactId>
    <version>1.0-SNAPSHOT</version>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.7.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>1.8</java.version>
        <java.encoding>UTF-8</java.encoding>
        <maven.build.timestamp.format>dd/MM/yyyy HH:mm:ss</maven.build.timestamp.format>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <project.build.sourceEncoding>${java.encoding}</project.build.sourceEncoding>
        <project.reporting.outputEncoding>${java.encoding}</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
    </dependencies>

</project>

Os dois chamam a classe CORS, colocada acima, só que ele sempre entra em response.setStatus(HttpServletResponse.SC_OK);.

O que pode ser ?

O erro era porque no Angular estava escrito Content-Type e no spring estava escrito Cotent-Type.

Assim como Access-Control-Allow-Headers estava errado não estava liberado.

UFA…

Obrigado a todos

1 curtida