Two questions regarding the use of the Corsregistry.allowOrigins() method

Asked

Viewed 67 times

0

I’m trying to do a post type resquest with credentials (token) for my spring boot built api.
But I’m having trouble specifying the source I pass as a parameter to the method CorsRegistry.allowOrigins().
The two origins I tried were : "http://localhost/*" and "https://italomp.github.io/interface-CRUD/".

The second source is an interface I hosted on github.io. But when making the request, I see in the browser console that a preflighted request error occurred.
This error should not happen because I configured the sources, headers and methods that the server accepts and these are the elements that the preflighted request analyzes.

So I ask:

  1. How to specify the origin "localhost" in CorsRegistry.allowOrigins()?
  2. Why doesn’t it work when I use the origin of github.io/?

JAVA CODE - Class with @Springbootapplication annotation:

package com.crud.rest;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.filter.GenericFilterBean;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureException;

/**
 * This is the main class of the project, because it has 
 * springBootApplication annotation. That's why it
 * is the responsible class for uploading the spring server.
 */
@SpringBootApplication
@ComponentScan("com.crud")
public class CrudApplication {

    /**
     * This static method start the spring server.
     * @param args: argument array.
     */
    public static void main(String[] args) {
        SpringApplication.run(CrudApplication.class, args);
    }
    
    /**
     * This method is responsible for filtering tokens for 
     * private routes. And here are noted all the private routes.
     * The '*' at the end of the route indicates that all the routes
     * beginning with "/v1/product/private/" are being passed as a 
     * parameter to the addUrlPatterns method.
     */
    @Bean
    public FilterRegistrationBean filterJwt(){
        FilterRegistrationBean filter = new FilterRegistrationBean();
        filter.setFilter(new TokenFilter());
        filter.addUrlPatterns("/v1/product/private/*");
        return filter;
    }

    @Configuration
    public class MyConfiguration {

        @Bean
        public WebMvcConfigurer corsConfigurer() {
            return (WebMvcConfigurer) new WebMvcConfigurerIplmts() {
                @Override
                public void addCorsMappings(CorsRegistry registry) {
                    registry.addMapping("/**")
                            .allowedOrigins("http://localhost/*") //this value can't be "*", because allowCredentials(true).
                            .allowedMethods("PUT", "DELETE","POST","GET")
                            .allowedHeaders("Content-type", "Authorization")
                            .allowCredentials(true)
                            .maxAge(3600);
                }
            };
        }
        
        public class WebMvcConfigurerIplmts implements WebMvcConfigurer{
            
            public WebMvcConfigurerIplmts() {
                
            }
        }
    }

JAVA CODE - Tokenfilter class:

package com.crud.rest;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.filter.GenericFilterBean;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureException;

/** 
 * This class is responsible for filtering the received tokens
 * in the requests.
 * @author Italo Modesto
 */
public class TokenFilter extends GenericFilterBean{

    /**
     * This method applies a filter on tokens to verify if it's valid.
     * 
     * Firstly, this method converts ServeletRequest to HttpServlerReques 
     * to be able to access its authorization attribute;
     * 
     * then this method extracts the authorization attribute from 
     * the request and check if the attribute is null or badly formatted (in
     * these cases, exceptions will be throws);
     * 
     * Finally, The token is extracted from the request and unpacked for it
     * can be passed as parameter to the filter chain.
     * 
     * The filter chain (in this case) call the resource requested.
     * 
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        String auth = req.getHeader("Authorization");                 
        if(auth == null || !auth.startsWith("Bearer ")) {
            throw new ServletException("Token inexistente ou mal formatado");
        }
        String token = auth.substring(7);
        try {
            Jwts.parser().setSigningKey("caneca").parseClaimsJws(token).getBody();
        }catch(SignatureException e) {
            throw new ServletException("Token inválido ou expirado");
        }
        chain.doFilter(request, response);
    }

}

BROWSER CONSOLE ERRORS SHOW:

Access to fetch at 'http://localhost:8080/api/v1/user/' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
script.js:43 

POST http://localhost:8080/api/v1/user/ net::ERR_FAILED
(anonymous) @ script.js:43
index.html:1 

Uncaught (in promise) TypeError: Failed to fetch

FRONT JAVASCRIPT CODE

let buttonUserRegistry = document.getElementById("buttonUserRegistry");
let buttonUserLogin = document.getElementById("buttonUserLogin");
let buttonCreateProduct = document.getElementById("buttonCreateProduct");
let buttonReadProduct = document.getElementById("buttonReadProduct");
let buttonUpdateProduct = document.getElementById("buttonUpdateProduct");
let buttonDeleteProduct = document.getElementById("buttonDeleteProduct");
let result = document.getElementById("result");

/**
 * Esse trecho de código adiciona um evento ao elemento
 * buttonUserRegistry.
 * 
 * evento: click
 * 
 * callback: função que coleta dados do novo usuario no form com 
 * id "userRegistry" e envia esses dados para p servidor através 
 * de uma requisição POT.
 * Esses daados compõe um novo usuário que será cadastrado no 
 * servidor
 */
buttonUserRegistry.addEventListener("click", function(){
    let form = document.getElementById("userRegistry");
    let inputName, inputLogin, inputPassword;
    let newUser, registerUrl, optRequest;
    for(e of form){
        if(e.name == "inputName"){
            inputName = e.value;
        }
        else if(e.name == "inputLogin"){
            inputLogin = e.value;
        }
        else if(e.name == "inputPassword"){
            inputPassword = e.value;
        }
    }
    newUser = {"name": inputName, 
               "login": inputLogin, 
               "password": inputPassword};
    registerUrl = "http://localhost:8080/api/v1/user/";
    optRequest = {method: "post",
                  headers: {"Content-type": "application/json"},
                  body: JSON.stringify(newUser)};
    fetch(registerUrl,optRequest)
    .then(resp => result.innerText = resp.status);
});

/**
 * Esse trecho de código adiciona um evento ao elemento 
 * "buttonUserLogin".
 * 
 * evento: click
 * 
 * callback: função que coleta dados do usuário que vai
 * efetuar login (esses dados estão no form que usa o
 * id "userLogin") e envia uma requisição POST para o
 * servidor.
 * E ainda, armaena o token recebido do servido no
 * localStorage.
 */
buttonUserLogin.addEventListener("click", function(){
    let form = document.getElementById("userLogin");
    let inputLogin, inputPassword;
    let user, loginUrl, optRequest;
    for(e of form){
        if(e.name == "inputLogin"){
            inputLogin = e.value;
        }
        else if(e.name == "inputPassword"){
            inputPassword = e.value;
        }
    }
    user = {"login": inputLogin, 
            "password": inputPassword};
    loginUrl = "http://localhost:8080/api/v1/auth/login";
    optRequest = {method: "post",
                  headers: {"Content-type": "application/json"},
                  body: JSON.stringify(user)};
    fetch(loginUrl, optRequest)
    .then(resp => resp.json())
    .then(tokenObject => window.localStorage.setItem("token", tokenObject.token))
    .then(result.innerText = "Login realizado com sucesso!");
});

buttonCreateProduct.addEventListener("click", function(){
    let form = document.getElementById("createProduct");
    let inputName, inputDescription, inputPrice;
    let newProduct, createProductUrl, optRequest, token;
    for(e of form){
        if(e.name == "inputName"){
            inputName = e.value;
        }
        else if(e.name == "inputDescription"){
            inputDescription = e.value;
        }
        else if(e.name == "inputPrice"){
            inputPrice = e.value;
        }
    }
    newProduct = {"name": inputName, 
                  "description": inputDescription, 
                  "price": inputPrice};
    createProductUrl = "http://localhost:8080/api/v1/product/private/";
    token = window.localStorage.getItem("token");
    optRequest = {method: "post",
                  headers: {"Content-type":"application/json",
                            "Authorization":"Bearer " + token},
                  credentials: "include",
                  body: JSON.stringify(newProduct)};
    fetch(createProductUrl, optRequest)
    .then(resp => {result.innerText = resp.status;});
    console.log(token);
});


/*
let inputName;
let inputLogin;
let inputPassword;
let inputDescription;
let inputPrice;
let inputProductID;
function inputCollector(){

}
for(e of form){
    if(e.name == "inputName"){
        inputName = e.value;
    }
    else if(e.name == "inputLogin"){
        inputLogin = e.value;
    }
    else if(e.name == "inputPassword"){
        inputPassword = e.value;
    }
    else if(e.name == "inputDescription"){
        inputDescription = e.value;
    }
    else if(e.name == "inputPrice"){
        inputPrice = e.value;
    }
    else if(e.name == "inputProductID"){
        inputProductID = e.value;
    }
}
*/`

  • kicking here, but I believe you need to specify the door, if you let. allowedOrigins("http://localhost/*") I believe it will consider port 80

  • For the origin "https://italomp.github.io/interface-CRUD/" I made an attempt specifying the port (https://italomp.github.io/interface-CRUD/:80), but it did not work. For localhost origin I don’t know which port I should specify as I think my local application will run on different ports each time I run the application...

  • the right would be italomp.github.io:80/interface-CRUD, but as I said earlier, when you do not put anything it already assumes that the port is 80, in your local case what I imagine localhost:8080, since it is what your front is calling, Another thing I noticed is that you’re trying to send an authorization token but I didn’t see on your back where it’s being treated, anyway, it’s hazy, I think you need to give more details

  • I edited my question and added the class responsible for checking the validity of the token, Lucas. But I can make this request using the Postman program, so I believe that there is no problem in the token processing, but in the CORS itself. This is the link to the repository where the code (API) is hosted: https://github.com/italomp/API-RESTful-using-spring-boot

  • opened your project here and tested using the github.io api,, in allowedOrigins I left only "https://italomp.github.io" and it worked normally, I believe that locally if you put "localhost:8080" will also work

No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.