I have a frontend written in angular which runs on localhost:3002.
I have a backend written with Spring-boot which runs on localhost:8080.
I added a filter to handle CORS (which I found on SO and adapted to my need) :
#Component
public class CORSFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "http://localhost:3002");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
chain.doFilter(request, response);
}
public void destroy() {}
}
When I authenticate, I can see that the server sends a cookie :
This cookie is not sent with the following requests. This results in 401 responses :
I looked at the "resources" panel of the chrome console and found out that no cookie were stored.
Any ideas?
In the file where you configure your $httpProvider, add this line to specify you want to send credentials with cross-site requests:
$httpProvider.defaults.withCredentials = true;
Typically, AngularJS will automatically send these cookies with requests (for same-origin requests) but since your requests are cross-site then you have to manually configure this.
Related
This question already has answers here:
"Cross origin requests are only supported for HTTP." error when loading a local file
(30 answers)
Closed 2 years ago.
No matter what I try I continue to get error:
"Access to XMLHttpRequest at
'file:///C:/api/v1/backtest?{%22strategy_name%22:%22sma"}' from origin
'null' has been blocked by CORS policy: Cross origin requests are only
supported for protocol schemes: http, data, chrome, chrome-extension,
chrome-untrusted, https."
Here is the ajax call:
var inputs = {};
inputs.strategy_name = strategy_name;
inputs.start_date = document.getElementById("start_date").value;
inputs.end_date = document.getElementById("end_date").value;
inputs.formula = document.getElementById("formula").value;
inputs.symbol = document.getElementById("backtest_symbol").value
inputs.benchmark_symbol = document.getElementById("benchmark_symbol").value
let jsonStrategyInputs = JSON.stringify(inputs);
console.log("jsonStrategyInputs=",jsonStrategyInputs);
$.ajax({
type : "GET",
contentType : "application/json",
datatype : "json",
url : "/api/v1/backtest",
data : jsonStrategyInputs,
success : function(data){
//do a bunch of business logic
},
error: function(e) {
alert('Error: '+e);
}
});
Here is the Spring Boot controller code:
#CrossOrigin(origins = "*")
#RestController
#RequestMapping(path="/api/v1")
public class StrategyController {
#Autowired
private StrategyService strategyService;
#GetMapping(value = "/backtest")
#ResponseBody
public JsonResponse backtestStrategy(#RequestBody BacktestInputs inputs, BindingResult result) throws Exception {
bla bla
}
This gives noted exception. So I added this class to the project:
#Component
public class SimpleCORSFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
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() {}
}
Same error. I have tried countless combinations of similar post answers but still no luck. Back to the experts. Any suggestions?
Of note, calling a similar controller with a jquery method works fine, like this:
function loadWatchlist() {
$.getJSON("http://localhost:8080/api/v1/watchlist?name=My%20Portfolio", function (data) {
data.forEach(function (item) {
console.log(item.watchlistId.symbol);
});
}
EDIT
Interestingly, if I click the link in the browser console, it says "Invalid character found in the request target [/api/v1/backtest?{%22strategy_name%22:%22sma-cross-and-extreme-hi-lo%22,%22start_date%22:%221928-12-30%22,%22end_date%22:%222020-06-19%22,%22formula%22:%22LET%20InitialBuyStop=StopLoss(InitialBuy,H)\nLET%20TrailingBuyStop=StopLoss(TrailingBuy,5%)\nLET%20InitialSellStop=StopLoss(InitialSell,L);\nLET%20TrailingSellStop=StopLoss(TrailingSell,5%)\nLET%20CrossAboveSMA200=C(1)%3CSMA(200,1)%20AND%20C%3ESMA(200)\nLET%20CrossBelowSMA200=C(1)%3ESMA(200,1)%20AND%20C%3CSMA(200)\nLET%20AboveUpperEnvCh=C%3EEnvCh(200,20).Upper\nLET%20BelowLowerEnvCh=C%3CEnvCh(200,20).Lower\nLET%20YesterdayWasOut=Position(1)==0\nLET%20YesterdayWasIn=Position(1)==1\nLET%20HitBuyStop=C%3EBuyStop\nLET%20HitSellStop=C%3CSellStop\nIF(CrossAboveSMA200)%20THEN%20BUY\nIF(CrossBelowSMA200)%20THEN%20SELL\nIF(AboveUpperEnvCh%20AND%20DnBar%20AND%20YesterdayWasIn)%20THEN%20SellAndSetBuyStop\nIF(AboveUpperEnvCh%20AND%20HitBuyStop%20AND%20YesterdayWasOut)%20THEN%20BuyAndResetStops\nIF(BelowLowerEnvCh%20AND%20YesterdayWasOut%20AND%20UpBar)%20THEN%20BuyAndSetSellStop\nIF(BelowLowerEnvCh%20AND%20YesterdayWasIn%20AND%20HitSellStop)%20THEN%20SellAndResetStops\nIF(TrailingBuyStop%3CBuyStop)%20THEN%20BuyStop=TrailingBuyStop\nIF(TrailingSellStop%3ESellStop)%20THEN%20SellStop=TrailingSellStop%22,%22symbol%22:%22SPP-500%22,%22benchmark_symbol%22:%22SP-500%22]"
It seems it is only url encoding the spaces and not {}, (), '=', '-' or the '%' in the 5%. May be I should not use JSON.stringify(inputs)? I also added more relevant info in this post above the ajax call.
the error you get is caused by your Chrome browser, so #CorssOrigin in the backend is no use.
this is cased since your ajax code is trying to access your own local resource.
to avoid this, you need to add some options when you execute Chrome browser.
here's a sample for executing Chrome on Windows
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="C:\Users\ユーザ名\Local\Google\Chrome\User Data"
I am developing a web application in spring boot and I retrieve the data from the database and produce a Json list and send it to a url(Rest Web Services).Then I get it from a get request in the Javascript using getJSON.
$.getJSON(
'http://localhost:8080/dataurl?i=1',
function(data) {
}
But it works fine with embedded tomcat server and does not work with standalone tomcat server.The error I get is
It is only returning a empty JSON array when I access the url in browser.
Why is it not working in standalone tomcat server.Is it also possible to add oauth2 security to this?Any help is appreciated.
If you want to enable CORS you should create filter.
#Component
public class CorsConfig implements Filter {
private final Logger log = LoggerFactory.getLogger(CorsConfig.class);
public CorsConfig() {
log.info("SimpleCORSFilter init");
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me, Authorization");
chain.doFilter(req, res);
}
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void destroy() {
}
}
This will add necessary headers for CORS.
The problem was the with postgresql maven dependency.When I changed the dependency it worked.Hope it helps anyone
In my web application I used owasp ZED Tool to check security vulnerability. I found that X-Content-Type-Options and Content-Type headers are not set.
In my cross filter, I have added the headers in HTTPResponse object
#WebFilter("/*")
public class CrossFilter implements Filter {
private static CoreLogger logger=LoggerFactory.getLogger(FirstServlet.class);
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filter) throws IOException,
ServletException {
try{
HttpServletResponse httpServletResponse = (HttpServletResponse ) servletResponse ;
httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
httpServletResponse.setHeader("Access-Control-Allow-Headers", "origin, content-type, accept, authorization");
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
httpServletResponse.setHeader("Access-Control-Max-Age", "1209600");
httpServletResponse.setHeader("X-Frame-Options", "SAMEORIGIN");
httpServletResponse.setHeader("X-XSS-Protection", "1; mode=block");
httpServletResponse.setHeader("X-Content-Type-Options", "nosniff");
httpServletResponse.setHeader("Content-Type", "text/plain");
filter.doFilter(servletRequest, servletResponse);
}catch(Exception exc){
logger.info(exc.getMessage());
if(logger.isDebugEnabled()){
logger.error(exc.getMessage(),exc);
}
}
}
Now when I am trying to access the application over browser, it shows me the source of HTML . I thought I have added text/plain was wrong and I tried text/html , but still error persists.
Could anyone help me out if the way I am doing is wrong ?
I have read many questions and answers regarding Angular $http data service calling into another application Web Api. Yes I seen that some people say the reason "Postman" is allowed in is because its like 3rd party external app etc..
In the past I did have control of the Web Api in which i installed CORS etc..
However, I am thinking that something has to be POSSIBLE as several stackoverflow question and answers did indeed have answers that were giving me HOPE
Here is the error
XMLHttpRequest cannot load http://localhost:60127/api/Product/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:60128' is therefore not allowed access.
Project with Web Api code
public class ProductController : ApiController
{
// GET api/<controller>
public IHttpActionResult Get() {
IHttpActionResult ret = null;
// ....
}
URL of Web api (works with Postman)
http://localhost:60127/api/Product/
Angular code
function productList() {
//http://localhost:60127/api/Product/
//dataService.get("/api/Product")
dataService.get("http://localhost:60127/api/Product/")
.then(function (result) {
vm.products = result.data; // result is an http status
debugger; // stop to see the code
},
function (error) {
handleException(Error);
});
}
In WebAPiConfig Class you need to enable Cors while registering WebAPiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.EnableCors(new System.Web.Http.Cors.EnableCorsAttribute("*", "*", "*"));
}
}
have u enabled CORS? and add something like:
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class ProductController : ApiController
{
.....
}
If you have different origin for server and client , you need to set Access-Control-Allow-Origin header to true on server side,
response.getHttpHeaders().add("Access-Control-Allow-Origin", "*"); // will alow reuest from all API
So if you are using filter you can do like this
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, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
chain.doFilter(req, res);
}
What I want to do: Call a cross-domain SOAP-Service from JavaScript using jQuery with the jQuery Soap plugin (by Remy Blom). (that is, I call $.soap(); in JavaScript)
What I did: CORS Setting on the server side (CXF) are working (using the org.eclipse.jetty.servlets.CrossOriginFilter), so the following is present in the answer:
Access-Control-Allow-Head... X-Requested-With,Content-Type,Accept,Origin
Access-Control-Allow-Meth... GET,POST,OPTIONS,HEAD
Access-Control-Allow-Orig... http://localhost:8082
Content-Type application/soap+xml;charset=UTF-8
What is missing: Firefox and Chrome send preflight OPTIONS requests prior to the POST request for the SOAP call. Obviously SOAP does not allow the OPTIONS verb.
It does not work with SoapUI (5.0) as well as CXF (2.7.7). It is even stated in a comment in org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor line 130ff:
/*
* Reject OPTIONS, and any other noise that is not allowed in SOAP.
*/
So, my question is: How can I modify my SOAP servcie implementation (using CXF), such that the OPTIONS request returns successfully?
Even if it's a little bit late, I had the same problem recently and maybe it will help future travelers.
In the case of an OPTIONS request you may not continue with the FilterChain.
I created a simple CORSFilter, which looks like this:
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*
public class CORSFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
resp.addHeader("Access-Control-Allow-Origin", "*");
resp.addHeader("Access-Control-Allow-Methods", "GET, POST");
resp.addHeader("Access-Control-Allow-Headers", req.getHeader("Access-Control-Request-Headers"));
if (!req.getMethod().equalsIgnoreCase("OPTIONS")) {
chain.doFilter(request, response)
}
}
#Override
public void destroy() {}
}
And I added the following to my web.xml:
<filter>
<filter-name>CORSFilter</filter-name>
<filter-class>CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORSFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>