Reputation: 320
I am using as Server-side Spring-boot and providing a dummy service for test
where my ServiceCaller.java=
package com.user.server.mfw;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.handler.MappedInterceptor;
@RestController
public class ServiceCaller {
@CrossOrigin(allowedHeaders="*",allowCredentials="true")
@RequestMapping(value="/serviceCaller",method=RequestMethod.POST, headers="content-type=text/*")
@ResponseBody
String serviceListener(@RequestParam("serviceName") String serviceName,HttpSession session,HttpServletRequest theHttpServletReq ) throws IOException
{
if(!serviceName.isEmpty())
{
byte[] encoded = Files.readAllBytes(Paths.get("C://Users//something//Desktop//asd.json"));
return new String(encoded, "UTF-8");
}
return "gelemedi";
}
private void checkActiveSessionControl(HttpSession session)
{
System.out.println("Session Id:" + session.getId() +" // " + session.getCreationTime());
if(session == null)
System.out.println("Null");
else if(session.isNew())
System.out.println("New");
else
System.out.println("Old");
}
}
where my client-side is a ionic framework and based on angular.js...
Controller.js
$scope.getInfo = function() {
$http({
url: SERVER_ENDPOINT.url + '/serviceCaller',
method: 'POST',
params: {serviceName: 'deneme'},
withCredentials: true
}).then(function(result) {
var alertPopup = $ionicPopup.alert({
title: 'ALOHA!',
template: 'dksjd ' + result
});
$scope.memberInfo = result.data.accountNumber;
}, function() {
var alertPopup = $ionicPopup.alert({
title: ' failed!',
template: 'da'
});
}
);
};
Basically I get a "invalid HTTP status code 403" when I use POST method instead of GET. However I would like to use POST for calling instead of GET. However I could not figure out where I am making a mistake....
any solution will be appreciated!
Upvotes: 1
Views: 6482
Reputation: 3033
I found the explanation of preflight request very clear in answer to question Angularjs Post not sending headers to Spring JWT.
Since you are using Spring Security, you have to enable CORS at Spring Security level as well to allow it to leverage the configuration defined at Spring MVC level as:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()...
}
}
Here is very excellent tutorial explaining CORS support in Spring MVC framework.
This enables HttpMethod.Options
request to include headers in preflight request.
Upvotes: 0
Reputation: 149
If your browser is sending a pre-flight OPTIONS request , all you have to do is to allow that in your WebSecurity configuration by allowing http OPTIONS.
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
Upvotes: 7
Reputation: 6581
As shown in the AngularJS docs
XSRF is a technique by which an unauthorized site can gain your user's private data. Angular provides a mechanism to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie (by default, XSRF-TOKEN) and sets it as an HTTP header (X-XSRF-TOKEN). Since only JavaScript that runs on your domain could read the cookie, your server can be assured that the XHR came from JavaScript running on your domain. The header will not be set for cross-domain requests.
so the default header is x-xsrf-token.
Add this filter in your websecurityconfiguration after CsrfFilter
public class CsrfHeaderFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie==null || token!=null && !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
}
add the filter as shown here:
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()...
.and()
.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
}
}
Upvotes: 1
Reputation: 2203
I think you're not passing any parameter using this anotation:
@CrossOrigin(allowedHeaders="*",allowCredentials="true")
@RequestMapping(value="/serviceCaller",method=RequestMethod.POST, headers="content-type=text/*")
@ResponseBody
String serviceListener(@RequestParam("serviceName") String serviceName,HttpSession session,HttpServletRequest theHttpServletReq ) throws IOException
{
you should replace value="/serviceCaller"
by value="/{serviceCaller}"
EDIT
please add this class to your project to solve the CORS problems
@Component
public class SimpleCORSFilter implements Filter {
@Override
public void init(FilterConfig fc) throws ServletException {}
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletResponse response = (HttpServletResponse) resp;
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");
chain.doFilter(req, resp);
}
@Override
public void destroy() {}
}
Upvotes: 1