I'm having trouble trying to send a custom header param from my frontend to the controller.
I've set the endpoint to get the header param:
public ResponseEntity<DashboardBean> atualizarDadosDashboard(#RequestHeader(name = "idEmpresa") Long idEmpresa){
But when I try to consume this endpoint, I get failed response and the application doesn't log any error.
Here I have the browser console showing the failed request:
The second dashboard request is a OPTIONS type. The first is the GET request.
Here you can see the failed request headers with the custom header "idEmpresa":
I'm using Angular on the frontend. As you can see below, I'm adding the header to the request:
....
protected httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': this.token,
'idEmpresa': String(this.idEmpresa)
})
};
atualizarDashboard(): Observable<DashboardModel> {
return this.httpClient.get<DashboardModel>(this.baseUrl, this.httpOptions);
}
....
On my spring boot application there is nothing on the logs about this request!!
Problem solved.
I have a CORS Filter in my application. I had to add my custom header param to the
Access-Control-Allow-Headers
list to allow it. After that, the endpoint was consumed and worked as expected.
This is how my Filter is now:
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCORSFilter implements Filter {
private final Log logger = LogFactory.getLog(this.getClass());
#Override
public void init(FilterConfig fc) throws ServletException {
logger.info("SimpleCORSFilter loaded");
}
#Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) resp;
HttpServletRequest request = (HttpServletRequest) req;
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, Content-Type, " +
"Authorization, credential, X-XSRF-TOKEN, idEmpresa");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, resp);
}
}
#Override
public void destroy() {
}
}
Related
I'm getting error while sending signup information to java spring-boot project from angular. I've tried thousands ways to resolve it but all in vain. Can't figure it out whats stopping java project to accept the request.
Error in console:
Access to XMLHttpRequest at 'http://localhost:8090/bites/service/signup' from origin 'http://localhost:4200' has been blocked by CORS policy: Request header field domain is not allowed by Access-Control-Allow-Headers in preflight response.
Here's my java code:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
try {
System.out.println("inside filter>>>>");
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "http://localhost:4200");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods",
"ACL, CANCELUPLOAD, CHECKIN, CHECKOUT, COPY, DELETE, GET, HEAD, LOCK, MKCALENDAR, MKCOL, MOVE, OPTIONS, POST, PROPFIND, PROPPATCH, PUT, REPORT, SEARCH, UNCHECKOUT, UNLOCK, UPDATE, VERSION-CONTROL");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Key, Authorization");
chain.doFilter(request, response);
}catch(Exception ex) {
ex.printStackTrace();
}
}
I know that angular signup form is sending accurate request with credentials to the java project but on java side request is denying.
Seeking help.
I'm trying my java application to accept request from angular project
Could you add the configuration:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
final ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("http://localhost:4200");
}
};
}
}
I'm using SpringBoot 2.5.6.
I tryto upload file via byte array in the FileController class:
#PostMapping("/uploadFileViaStream")
public JSONObject uploadFile1(#RequestBody byte[] bytes) {
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
String fileName = genUUID();
String fileId = null;
fileId = fileService.uploadFile("", fileName, inputStream);
Map<String, Object> map = new HashMap<>(1);
map.put("file", fileId);
return ZheliResult.ok(map);
}
And add #CrossOrigin(origins="*") on the FileController class.
The Chrome says No 'Access-Control-Allow-Origin' header is present on the requested resource. which is a CORS issue.
Then I delete #CrossOrigin(origins="*"), and add a configuration class:
#Configuration
public class MvcConfiguration implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/*")
.allowedOriginPatterns("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT","PATCH", "HEAD", "OPTIONS")
.maxAge(3600);
}
}
Still doesn't work.
Then I delete this and turn to Nginx to configure CORS:
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods *;
add_header Access-Control-Allow-Headers *;
It does work but after a while the CORS problem appeared again.
Then I configure the SpringCloud Gateway in the bootstrap.yml:
gateway:
globalcors:
add-to-simple-url-handler-mapping: true
cors-configurations:
'[/**]':
allowedOrigins: "*"
allowedHeaders: "*"
allowedMethods: "*"
allowCredentials: true
The Chrome says:
The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.
If I change * int the Nginx or Gateway to http://172.20.10.9:8080, The Chrome says:
The 'Access-Control-Allow-Origin' header contains multiple values 'http://172.20.10.9:8080, http://172.20.10.9:8080', but only one is allowed.
So can anyone help me?
I would simply add filter requests and allow CORS to pass. The HIGHEST_PRECEDENCE order is importand. Do not neave it out!
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods",
"DELETE, GET, OPTIONS, POST, PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Key, Authorization");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
}
I want to accept origin as http://192.168.1.35:4200 and I created the CORSFilter like this in the springboot:
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class CORSFilter implements Filter {
public CORSFilter() {
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "http://192.168.1.35:4200");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PATCH, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Authorization, X-Auth-Token, Origin, Content-Type, Accept, Auth_Token");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void destroy() {
}
}
And I created the request like this to call the spring rest api from angular:
getAllUsers(): void {
this.accessToken = JSON.parse(window.sessionStorage.getItem('token')).access_token;
this.httpClient.get<User[]>(`${BASE_URL}/fam-users/user?access_token=${this.accessToken}`, httpOptions).subscribe(data => {
this.dataChange.next(data);
},
(err: ApiError) => {
this.snackBar.openSnackBar(err.error.message, 'close', 'red-snackbar');
});
}
When I send request, It says that
Access to XMLHttpRequest at 'http://192.168.1.35:8080/fam-users/user?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTAwNDMwODMsInVzZXJfbmFtZSI6ImFkbWluIiwiYXV0aG9yaXRpZXMiOlsiRkFfQU1FTkQiLCJGQV9ORVciXSwianRpIjoiOWViMzZjNzAtOGUwOS00YzViLWI0OWQtNDNmZTRhOTkzNDgzIiwiY2xpZW50X2lkIjoiY2xpZW50Iiwic2NvcGUiOlsicmVhZCIsIndyaXRlIiwidHJ1c3QiXX0.IETZOJE8tIqNc249HmTcJHuZpZFY1TP4PLcbqUOF3qc' from origin 'http://192.168.1.35:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
But all other requests from 'http://192.168.1.35:4200' are working fine.
Can Someone guide me to solve this issue?
There is a #CrossOrigin annotation in spring boo, for example:
#CrossOrigin(origins = "http://localhost:9000")
#GetMapping("/greeting")
public Greeting greeting(#RequestParam(required=false, defaultValue="World") String name) {
System.out.println("==== in greeting ====");
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
for more please have a look
I know there are lots of posts regarding the same problem, but none of it resolve my issue.
I have a springboot microservice application with the following API
#RestController
#RequestMapping({ "/sample" })
public class SampleController {
#CrossOrigin(origins = "http://192.168.0.31:8080", allowCredentials = "false", allowedHeaders = "*")
//#CrossOrigin//(allowCredentials = "false")
#RequestMapping(value="/welcome" , method=RequestMethod.POST, produces={"application/json"})
public JSONObject getWelcomeResponse(#RequestParam Map<String,String> request){
JSONObject response=new JSONObject();
response.put("response", "Welcome user");
System.out.println("Complterd ****");
return response;
}
}
properties file
server.port=8081
security.user.name=test
security.user.password=test123
#security.basic.enabled=false
And my client code is
$(document).ready(function(){
$.ajax({
url: "http://192.168.0.31:8081/sample/welcome",
type : "POST",
crossDomain:true,
crossOrigin:true,
beforeSend: function (xhr) {
// Use BASIC Authentication
xhr.setRequestHeader ("Authorization", "Basic " + btoa("test:test123"));
},
error: function(xhr, status, errorThrown) {
alert(status, errorThrown);
// Error block
console.log("xhr: " + xhr);
console.log("status: " + status);
console.log("errorThrown: " + errorThrown);
}
})
.then(function(data, status, xhr) {
alert(data);
console.log("xhr: " + xhr);
console.log("status: " + status);
console.log("data: "+ data);
$('.message').append(JSON.stringify(data));
});
});
When I disable the basic auth, The cors request is works fine. But if it enabled it gives 401 preflight request error.
I have tried #CrossOrigin with default as well as customized way also. But getting the same error. Also tried with a filter class like below.
#EnableWebMvc
public class MyAppConfigurations implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpServletRequest httpRequest = (HttpServletRequest) request;
if("OPTIONS".equalsIgnoreCase(httpRequest.getMethod())) {
httpResponse.setStatus(HttpServletResponse.SC_OK);
System.out.println("filterde response");
} else {
chain.doFilter(request, response);
}
}
}
Can somebody help me to figure out, what I am missing on this code.
You have to create CORS FILTER for your Spring MicroService
import org.springframework.core.Ordered;
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;
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
if (response instanceof HttpServletResponse) {
addCorsHeader(response);
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
filterChain.doFilter(req, res);
}
}
}
private void addCorsHeader(HttpServletResponse response) {
response.addHeader("Access-Control-Allow-Origin", "http://localhost:4200"); // Update with yours
response.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, HEAD");
response.addHeader("Access-Control-Allow-Credentials", "true");
response.addHeader("Access-Control-Allow-Headers", "Authorization, X-PINGOTHER, Origin, X-Requested-With, Content-Type, Accept");
response.addHeader("Access-Control-Max-Age", "1728000");
}
#Override
public void destroy() {
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
Add #CrossOrigin before class like
#RequestMapping({ "/sample" })
#CrossOrigin(origins = "http://192.168.0.31:8080")
public class SampleController {
try adding in your /welcome Rest Controller
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
According to the CORS specification, the CORS preflight request must be accepted without any authentication.
You have to configure your web server or Spring Security to disable authentication on all OPTIONS requests related to preflight.
I am building the authentication for my angular app using JWT token.
For any request to the rest api, I want that spring MVC check for the token in the header of the http request except when the http request is /login (to create a new token).
I am having an issue with my cors filter. It is sending a 401 status after the user is logged in successfully. The token sent in the "authorization" header is not taken into account.
angular service
getListe(): Promise<any> {
let header = new Headers();
header.append("authorization", localStorage.getItem("token"))
return this.http.get(URL_API_REST + 'liste', header)
.toPromise()
.then(response => response.json())
.catch(this.handleError);
}
Spring Cors Filter
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request= (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type");
response.setHeader("Access-Control-Expose-Headers", "x-requested-with");
if(!request.getRequestURI().equals("/rest/rest/login")) {
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization");
response.setStatus(HttpServletResponse.SC_OK);
}
/*if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
*/
chain.doFilter(req, res);
}
Spring Authentication Filter
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request= (HttpServletRequest) servletRequest;
String token = request.getHeader("token");
if(token != null){
System.out.println("Présence d'un token");
}
else{
if(!request.getRequestURI().equals("/rest/rest/login"))
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
filterChain.doFilter(request, response);
}
Is there something am I missing ?
I don't have time to try to analyze code now, but I recommend you this project in GitHub that show a simple login system using JWT and Java. I've used it as an example to implement JWT in some of my systems and it worked perfectly. Hope it helps.
I had a hard time dealing with this issue, but I hope the answers will spare the time for some.
Actually, I figured out that my angular wasn't sending the header authorization in the request headers. To solve that issue, I used the RequestOptions in my service Angular.
service Angular
getListe(): Promise<any> {
let header = new Headers();
header.append("authorization", localStorage.getItem("token"))
let options = new RequestOptions({headers: header})
return this.http.get(URL_API_REST + 'liste', options)
.toPromise()
.then(response => response.json())
.catch(this.handleError);
}