Angular requested backend Spring boot Application to generate Excel's interface, and a cross-domain error occurred. But I've already done cross-domain processing on the back end, so what's going on?
Access to XMLHttpRequest at 'http://localhost:8080/api/ticket/myTicketDownload' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
#CrossOrigin
#GetMapping("/ticket/myTicketDownload")
public void myTicketDownload(HttpServletResponse response ) throws IOException {
response.reset();
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String day = DateUtils.localDateformat(LocalDate.now());
String fileName = URLEncoder.encode("myTicket"+day, "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
TicketQueryDto ticketQueryDto = new TicketQueryDto();
ticketQueryDto.setPkMyTicket("111");
List<TicketVo> allTicketData = iTicketGeneralService.getMyTicketData(ticketQueryDto);
EasyExcel.write(response.getOutputStream(), TicketVo.class).sheet(day).doWrite(allTicketData);
}
//Angular
ExportMyTicket(){
return this.http.get<void>(`http://localhost:8080/api/ticket/myTicketDownload`)
}
You can't configurate CORS on the client side. Adding headers doesn't change anything. You need to configurate it in the backend. There must be somewhere a collection of domains the backend accepts.
Related
I have follow this tutorial of angular 7 to make a CRUD functions. I publish the project into my IIS but I am having an error (Image)
Access to XMLHttpRequest at 'http://192.168.120.178:2030/Api/Employee/UpdateEmployeeDetails/' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I tried to add the header in Update Code to allow the CORS but its the same.
The error also applies to other functions (Save, Delete)
Angular Code
updateEmployee(employee: Employee): Observable<Employee> {
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Access-Control-Allow-Credentials': "true",
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods': 'GET',
'Access-Control-Allow-Origin': '*'
})
};
return this.http.put<Employee>(this.url + '/UpdateEmployeeDetails/',
employee, httpOptions);
}
API Code
[HttpPut]
[Route("UpdateEmployeeDetails")]
public IHttpActionResult PutEmaployeeMaster(EmployeeDetail employee)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
try
{
EmployeeDetail objEmp = new EmployeeDetail();
objEmp = objEntity.EmployeeDetails.Find(employee.EmpId);
if (objEmp != null)
{
objEmp.EmpName = employee.EmpName;
objEmp.Address = employee.Address;
objEmp.EmailId = employee.EmailId;
objEmp.DateOfBirth = employee.DateOfBirth;
objEmp.Gender = employee.Gender;
objEmp.PinCode = employee.PinCode;
}
int i = this.objEntity.SaveChanges();
}
catch (Exception)
{
throw;
}
return Ok(employee);
}
But If im running my project using a localhost API its okay. But in publish (IIS) im getting the CORS error. I spent one whole day already but unfortunately I didn't see a solution to my problem.
TL;DR: You actually have the CORS headers in the wrong direction.
The API (server side) needs to be the one returning the CORS headers as a way of signaling to the browser that you expected whatever domain the Angular UI is being served on (client side) to call your API.
See this article from Mozilla about CORS
If you think about it, it doesn't make sense for the client side / browser to set these CORS headers, because the client side can easily be compromised by a bad actor (such as chrome plugin, foreign javascript, etc.), and if the client side was in charge of these CORS headers, it would be really easy to make them be what a hacker wants them to be. Instead, they need to come from the server side - hinted at by the Access-Control-* prefix. It's the server's way of whitelisting domains it expects the front end to access it from.
Another way to think about it would be that I couldn't create a website that directly hit Facebook's API's if they have their CORS headers restricted to only allow *.facebook.com because I don't own that domain. CORS are also a protection layer to prevent bad actors from being able to use your server side APIs and spoof your front end to capture people's data.
if it is .net core go in Startup.cs and serve both back-end and front-end with https and enable CORS
public void ConfigureServices(IServiceCollection services)
{
...
services.AddCors();
...
}
public void Configure(IApplicationBuilder app)
{
...
app.UseCors(builder =>
builder.WithOrigins("YOUR_FRONTEND_URL")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials());
...
}
Source
Web API 2 (Prior Core)
Install-Package Microsoft.AspNet.WebApi.Cors
App_Start\WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute(
origins: "YOUR_FRONTEND_URL",
headers: "*",
methods: "*");
config.EnableCors(cors);
...
}
More Information
I have an angular 5 app that makes a POST request my Spring Boot server. What is done in my backend is simply doing a redirection to another location of my angular application.(I am doing this because I am simulating the redirection that I must perform when an external service makes a POST request to my backend) but when from my angular application I make the post request to my backend to perform the redirection a problem occurs:
Access to XMLHttpRequest at
'http://localhost:4200/payment_resume?state=1&billNumber=234343&description=descr&value=120.000&method=Visa'
(redirected from 'http://localhost:8083/v1/redirect') from origin
'null' has been blocked by CORS policy: Request header field
Authorization is not allowed by Access-Control-Allow-Headers in
preflight response.
what I do not understand is why there is a problem with CORS, if I made the debug in backend and the request is accepted and handled by my server giving a redirect response ... when my backend responds with the redirection in my angular application the error appears...
Backend code:
#RequestMapping(value = "/redirect", method = RequestMethod.POST)
#Transactional
public void returnData(UriComponentsBuilder uriComponentsBuilder, final HttpServletRequest request,
final HttpServletResponse response) throws IOException {
String transactionState="1";
String billCode="234343";
String description="descr";
String billValue="120.000";
String paymentMethod="Visa";
response.sendRedirect(hostname+"/payment_resume?state="+ transactionState
+"&"+"billNumber="+billCode
+"&"+"description="+description
+"&"+"value="+billValue
+"&"+"method="+paymentMethod);
return;
}
CORS Configuration:
#Configuration
#EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedOrigin("*");
configuration.addAllowedHeader("*");
configuration.setAllowedMethods(Arrays.asList("GET","POST","PUT","PATCH","DELETE","OPTIONS"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Frontend code:
redirect(){
this.http.post(environment.apiUrlBase+"/redirect","").subscribe();
}
my question is what configuration should I do in my angular application so that this can work?
Many Thanks!
I also got the same issue and then I used CrosFilter. Add below Bean and try
#Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
configuration.addAllowedOrigin("*");
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("OPTIONS");
configuration.addAllowedMethod("HEAD");
configuration.addAllowedMethod("GET");
configuration.addAllowedMethod("PUT");
configuration.addAllowedMethod("POST");
configuration.addAllowedMethod("DELETE");
configuration.addAllowedMethod("PATCH");
source.registerCorsConfiguration("/**", configuration);
return new CorsFilter(source);
}
I am trying to connect from Javascript to Acumatica with following code:
var xmlhttp = new XMLHttpRequest();
URL = "h ttps://demo.mytestwebsite.com/entity/auth/login/";
xmlhttp.open("POST", URL, false);
xmlhttp.setRequestHeader("Authorization", "Basic " + btoa("Admin:hgfjk"));
xmlhttp.send();
And getting error:
VM2372:7 OPTIONS https ://demo.mytestwebsite.com/entity/auth/login/ 405 (Method Not Allowed)
connect # VM2372:7
(anonymous) # VM2374:1
VM2372:7 XMLHttpRequest cannot load http s://demo.mytestwebsite.com/entity/auth/login/. Response for preflight has invalid HTTP status code 405
connect # VM2372:7
(anonymous) # VM2374:1
VM2372:7 Uncaught DOMException: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http s://demo.mytestwebsite.com/entity/auth/login/'.
at connect (:7:15)
at :1:1
This issue is caused by CORS, i.e. the web browser does not get the necessary response from IIS hosting Acumatica, to satisfy CORS. CORS is a mechanism of increasing security in browsers.
When encountering this issue you can also run into these sorts of errors:
Response for preflight has invalid HTTP status code 500
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource
As of Acumatica Version 6.10.0945, this is how you configure IIS to make it CORS compatible for Acumatica for this type of requirement.
Add the following HTTP Response Headers within IIS.
Name: Access-Control-Allow-Origin Value: http://5.5.5.5 (IP Address or URL of the site that will connect to Acumatica - eg. https://mycompany.zendesk.com)
Name: Access-Control-Allow-Headers Value: Content-Type, cache-control
Name: Access-Control-Allow-Credentials Value: true
When values are added from Internet Information Services (IIS) Manager, they also appear in the web.config file in the Acumatica application folder as Custom Headers. For example - C:\Program Files (x86)\Acumatica ERP\MainAcumatica\web.config
I experienced issues adding the entries directly to web.config so suggest it is done through IIS.
Secondly, an entry needs to be made into the Global.asax file located in the same directory as web.config
This is the complete file with the function to insert being Application_BeginRequest():
<%# Application Language="C#" Inherits="PX.Web.PXApplication" %>
<script RunAt="server">
protected override void MergeAdditionalAssemblyResources()
{
PX.Web.UI.AssemblyResourceProvider.MergeAssemblyResourcesIntoWebsite<PX.Web.Controls.PXResPanelEditor>();
}
protected override void Initialization_ProcessApplication()
{
Initialization.ProcessApplication();
}
protected void Application_BeginRequest() {
if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS") {
Response.Flush();
}
}
</script>
The function Application_BeginRequest() in this file is flushing the response generated by the application for CORS OPTIONS requests, and letting IIS handle it with its header configuration.
OPTIONS requests are made by the CORS mechanism in the web browser, referred to as ‘pre-flight’, in order to confirm that the target server for the request is CORS compliant.
These settings will resolve the issue reported.
Instead of using basic authentication, try to pass username, password, company, branch, and locale (company, branch, and locale are optional) as request body following the sample below:
URL = "http://10.211.55.3/StackOverflow/entity/auth/login"; //Your URL
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", URL, false);
xmlhttp.setRequestHeader("Content-Type", "application/json");
var params = "{ name: '<username>', password: '<password>' }";
xmlhttp.send(params);
I need to access my web api hosted remotely from my react app. On the server side i did below to allow cross domain communication:
import javax.ws.rs.core.Response;
import com.mypackage.ResponseDto;
#Override
public Response fetch(String id, String env) throws ServiceException
{
ResponseDto res = new ResponseDto();
res = updateResp(id, env); // not important
return Response.ok().header("Access-Control-Allow-Origin","*").entity(res).build();
}
When i check from postman i can see cors header correctly set as below:
access-control-allow-origin →*
content-type →application/json
date →Wed, 16 Aug 2017 11:07:16 GMT
server →web
transfer-encoding →chunked
But when i access the same endpoint from react app, browsers starts complaining with below error:
Fetch API cannot load
http://myservices.com/myservice-app/services/. Response to
preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:3000' is therefore not allowed
access. If an opaque response serves your needs, set the request's
mode to 'no-cors' to fetch the resource with CORS disabled
Any idea whats going on here?
Edit#1
Did below change still see the same error:
return Response.ok()
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "POST, GET, PUT, UPDATE, OPTIONS")
.header("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With")
.entity(response).build();
I have no experience with whatever Java library you're using, but something like this must work:
#Override
public Response options() throws ServiceException
{
ResponseDto res = new ResponseDto();
return Response.ok().header("Access-Control-Allow-Origin","*").entity(res).build();
}
If the library works like I think it does, this will send a 200 OK on every OPTIONS request you send to your server, with header Access-Control-Allow-Origin = *. That's what you should be aiming for.
I'm new to web development so let me explain:
I want my Python Tornado server to communicate with a web page. My web page uses WebSockets and the onmessage function to print what it should receive from the Tornado server. Basically, here is the HTML JavaScript part:
$(document).ready(function() {
var myURL = "http://localhost:8888";
var source = new EventSource(myURL, { withCredentials: true }); // Access-Control-Allow-Origin
...
source.onmessage = function(event) {
console.log("received new event!");
};
...
}); // ready()
I'm setting the withCredentials parameter to true so CORS are enabled.
On the Tornado side, I have a WebSocket class which is supposed to answer back, but I don't know how to set the header to have Access-Control-Allow-Origin enabled. Here is the tornado code:
class EchoWebSocket(tornado.websocket.WebSocketHandler):
def check_origin(self, origin):
return True
def on_message(self, message):
self.write_message(u"Received message: " + message)
def make_app():
return tornado.web.Application([ ('/', EchoWebSocket), ])
if __name__ == '__main__':
app = make_app()
app.listen(8888)
print 'listening on port 8888...'
# start main loop
tornado.ioloop.IOLoop.current().start()
I'm stuck with the following error in my browser!
GET http://localhost:8888/ [HTTP/1.1 400 Bad Request 1ms]
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8888/. (Reason: CORS header 'Access-Control-Allow-Origin' missing).
What am I missing???
Your javascript is using EventSource but your server is serving WebSockets. These are two completely different things. You need to change one of those to match the other.