Unable to access a customized header in CORS environment using spring mvc and $http - angularjs

I have done an extensive search for the mentioned issue, but unable to find a workable solution.
Kindly have a look on some imp codes and suggest.
// My factory method that returns a promise
contactBackend : function(requestedMethod, requestedUrl,
requestedData) {
return $http({
method : requestedMethod,
url : backend + requestedUrl,
data : requestedData
});
}
//Actual Login method that calls the
loginC.validateLogin = function() {
welcomeMFactory.contactBackend("POST", "/rs/login",
loginC.user).then(
function(success) {
var msg = success.data.loginMsg;
if (msg == "login.valid") {
alert(JSON.stringify(success));
welcomeMFactory.moveToWidget("/home");
} else {
loginC.error = welcomeMFactory.printMsg(
true, msg);
}
},
function(error) {
loginC.error = welcomeMFactory.printMsg(true,
"Unable to reach backend for login");
});
}
// SpringController.xml
<mvc:cors>
<mvc:mapping path="/**" allowed-origins="http://localhost:8080"
allowed-headers="content-type,authentication" exposed-headers="content-type,authentication" />
</mvc:cors>
//Login Controller
#Autowired
private LoginRespI response;
#Autowired
private ProxyHandler proxyHandler;
#Autowired
private LoginServiceImpl loginServiceImpl;
#RequestMapping(method = RequestMethod.POST)
public LoginRespB authenticateUserLogin(#RequestBody LoginReqB request, HttpServletResponse resp) {
LoginDTO loginDTO = loginServiceImpl.validateLoginService(request.getUsername(), request.getPassword());
if (loginDTO != null) {
response.setLoginMsg("login.valid");
} else {
response.setLoginMsg("login.invalid");
}
Claims claims = Jwts.claims().setSubject("ABCDE");
claims.put("ID", "12345");
String toke = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, "ABCDE").compact();
resp.setHeader("Authentication", "Bearer: " + toke);
return (LoginRespB) (proxyHandler.getTargetObject(response));
}
OPTIONS req/resp headers
Login req/resp headers

Add this method to your code ,it will allow cros domain request
package org.codingpedia.demo.rest.util;
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.MultivaluedMap;
public class CORSResponseFilter
implements ContainerResponseFilter {
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
throws IOException {
MultivaluedMap<String, Object> headers = responseContext.getHeaders();
headers.add("Access-Control-Allow-Origin", "*");
//headers.add("Access-Control-Allow-Origin", "http://podcastpedia.org"); //allows CORS requests only coming from podcastpedia.org
headers.add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
headers.add("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, X-Codingpedia");
}
}

Related

Getting CORS error after deploying Spring boot service and UI through Google Compute Shell

I am new to google cloud and I have deployed a Spring Boot application and Angular JS application through Google Cloud Shell.
Started Spring Boot app by "java -jar MyAppName.jar &" command and UI server is started with "npm start". The web preview URL for UI is "https://8080-xx-123456789-default.region-zone.cloudshell.dev" and for Spring boot service rest end point is "https://8301-xx-123456789-default.region-zone.cloudshell.dev/maintenance". When this rest end point is invoked using Angular JS $http.post(), it is failing and browser console displays below error.
Access to XMLHttpRequest at 'https://8301-xx-123456789-default.region-zone.cloudshell.dev/maintenance' from origin 'https://8080-xx-123456789-default.region-zone.cloudshell.dev' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
8301-xx-123456789-default.region-zone.cloudshell.dev/maintenance:1 Failed to load resource: net::ERR_FAILED
My server.js in npm start command is:
var express= require('express');
var app=express();
app.use(express.static('myUIProjectName'));
app.get('/',function(req,res){
res.redirect('/');
});
app.listen(process.env.port || 8080,'127.0.0.1');
console.log('UI server is listening on port 8080');
My Angular JS controller code.
var loginController = app.controller('auditController', function ($scope, $http,
$rootScope,
$location, $window, ServiceProcessor, fileUploadService, PageNavigatorService,
DataTransferService, DownloadTransferService) {
$scope.uploadFile = function () {
$scope.expenditureList = [];
var file = $scope.myFile;
var uploadUrl = "https://8301-xx-123456789-default.region-
zone.cloudshell.dev/maintenance";
var promise = fileUploadService.uploadFileToUrl(file, uploadUrl);
promise.then(function (response) {
let calculationResponse = response.calculationResponse;
$scope.calculationResponse = calculationResponse;
let expenseNameToExpenseDetails = calculationResponse.expenseNameToExpenseDetails;
for (const [expenseName, expenditure] of Object.entries(expenseNameToExpenseDetails))
{
$scope.expenditureList.push(expenditure);
}
DataTransferService.set(calculationResponse);
}, function (response1, response2) {
$scope.serverResponse = 'An error has occurred';
});
};
app.service('fileUploadService', function ($http, $q) {
this.uploadFileToUrl = function (file, uploadUrl) {
//FormData, object of key/value pair for form fields and values
var fileFormData = new FormData();
fileFormData.append('file', file);
var deffered = $q.defer();
$http.post(uploadUrl, fileFormData, {
transformRequest: angular.identity,
// headers: { 'Content-Type': undefined }
headers: {'Content-Type': undefined,'withCredentials': true}
}).success(function (response) {
deffered.resolve(response);
}).error(function (response) {
deffered.reject(response);
});
return deffered.promise;
}
});
My Spring boot code is below:
#SpringBootApplication
#EnableConfigurationProperties({
FileStorageProperties.class
})
#ComponentScan({packages})
public class EasymaintenanceApplication {
public static void main(String[] args) {
SpringApplication.run(EasymaintenanceApplication.class, args);
}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("https://8301-xx-123456789-
default.region-zone.cloudshell.dev","http://127.0.0.1:5500");
}
};
}
}
Controller code:
#CrossOrigin(origins = "*")
#RestController
//#RequestMapping ("/maintenanceService")
public class MaintenanceController {
#Autowired
private MaintenanceBL maintenanceBL;
#Autowired
private FileStorageService fileStorageService;
private static final Logger logger = LoggerFactory.getLogger(MaintenanceController.class);
#CrossOrigin(origins = "*")
#PostMapping("/maintenance")
public UploadFileResponse calculateMaintenance(#RequestParam("file") MultipartFile file)
throws Exception {
UploadFileResponse response = null;
try {
String fileName = fileStorageService.storeFile(file);
String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
.path("/downloadFile/")
.path(fileName)
.toUriString();
CalculationResponse calculationResponse = maintenanceBL.readMaintenanceFile(fileName);
response = new UploadFileResponse(fileName, fileDownloadUri,
file.getContentType(), file.getSize(), calculationResponse);
} catch (Exception e) {
logger.error("Exception occurred while calculating maintenance", null, e);
}
return response;
}
}
CORSHandler class (doFilter method is hitting successfully):
#Component
public class CORSHandler implements Filter {
public static final String X_CLACKS_OVERHEAD = "X-Clacks-Overhead";
#Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
System.out.println("Request is hitting");
HttpServletResponse response = (HttpServletResponse) res;
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS");
response.addHeader("Access-Control-Allow-Headers", "DNT,X-CustomHeader,Keep-Alive,User-
Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range");
System.out.println("Request is chained");
chain.doFilter(req, res);
}
#Override
public void destroy() {}
#Override
public void init(FilterConfig arg0) throws ServletException {}
}
Please try using one of the allowed origins in your Controller instead of just "*"
Like in your corsConfigurer Bean you have allowed "https://8301-xx-123456789-default.region-zone.cloudshell.dev" and "http://127.0.0.1:5500"
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("https://8301-xx-123456789-
default.region-zone.cloudshell.dev","http://127.0.0.1:5500");
}
};
}
So in your controller please check by using one of these origins like :
#CrossOrigin(origins = "http://127.0.0.1:5500")
#PostMapping("/maintenance")
public UploadFileResponse calculateMaintenance(#RequestParam("file") MultipartFile
file)
throws Exception {
UploadFileResponse response = null;
try { ...
If that works, It will be great, Regards !
Yes, this happens when you try to communicate between different servers or the same server but with different port addresses. You need to add a cross-origin configuration on your microservice end. Some time (happened with me) this #crossorigin annotation will override by another configuration, then in that case you need to add a global filter to wite list, all the requested coming to your APIs.
Here, I am sharing a small code snippet to adding a filter to remove cross-origin issue.
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CORSFilter extends GenericFilterBean implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setHeader("Access-Control-Allow-Origin", "*");
httpResponse.setHeader("Access-Control-Allow-Methods", "*");
httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
httpResponse.setHeader("Access-Control-Allow-Headers", "*");
httpResponse.setHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept, X-Auth-Token, X-Csrf-Token, Authorization");
httpResponse.setHeader("Access-Control-Allow-Credentials", "false");
httpResponse.setHeader("Access-Control-Max-Age", "3600");
System.out.println("********* CORS Configuration Completed *********");
chain.doFilter(request, response);
}
}
Now create a Bean of this class like below
#Bean
public FilterRegistrationBean corsFilterRegistration() {
FilterRegistrationBean registrationBean =
new FilterRegistrationBean(new CORSFilter());
registrationBean.setName("CORS Filter");
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(1);
return registrationBean;
}
That's it hope your issue will be resolved.

How to submit jwt token to Spring Security with ReactJs?

I have secured my API-endpoints of my Spring Boot Application with Spring Security.
On login, I generate a new jwt token and submit it to the user.
On data requests, I expect the user to submit the token in the header.
If I do this using postman, it works perfecty fine.
When I try to send the token with React, it fails (axios/fetch/superagent).
The issue is not the submission of the token itself because if I disable authorization I can read the authorization header with the controller.
Instead, Spring Security somehow does not recognize the header when it is sent via React.
I've tried adding another custom header to see if Spring allows that but that custom header is "blocked" aswell.
React:
axios(apiTest, {
async: true,
crossDomain: true,
method: "GET",
headers: {
Authorization: `Bearer ${this.props.token}`,
TestHeader: "RandomValue",
Accept: "*/*"
},
processData: false,
data: ""
})
.then(res => {
if (res.data !== undefined) {
console.log(res.data);
}
})
.catch(err => console.error(error));
Spring Security:
Token Filter:
#Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
#Value("${jwt.header}")
private String tokenHeader;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
//Usual Authorization header (is null with React-use)
final String requestHeader = request.getHeader(this.tokenHeader);
//Custom header (null)
System.out.println("Test Header: " + request.getHeader("TestHeader"));
if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
String authToken = requestHeader.substring(7);
JwtAuthentication authentication = new JwtAuthentication(authToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
chain.doFilter(request, response);
}
}
Config:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
#Autowired
private JwtAuthenticationProvider jwtAuthenticationProvider;
#Autowired
public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) {
authenticationManagerBuilder.authenticationProvider(jwtAuthenticationProvider);
}
#Bean
CorsFilter corsFilter() {
CorsFilter filter = new CorsFilter();
return filter;
}
#Bean
public JwtAuthenticationTokenFilter authenticationTokenFilterBean() {
return new JwtAuthenticationTokenFilter();
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.addFilterBefore(corsFilter(), SessionManagementFilter.class).csrf().disable().authorizeRequests()
.antMatchers("/Login").permitAll().antMatchers("/CloseConnection**").permitAll()
.antMatchers(HttpMethod.OPTIONS, "**").permitAll().anyRequest().authenticated().and()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler);
}
}
Any idea what the exact issue is and how to solve it?
Try this it worked for me
private String getToken(HttpServletRequest request) {
String header = request.getHeader("Authorization");
if (header != null && header.startsWith("Bearer ")) {
return authHeader.replace("Bearer ","");
}
return null;
}
axios call
axios.post(url,{
"data": 'sample',
},
{
headers: {
'Authorization':'Bearer '+token,
'Content-Type':'application/json'
}
})
.then((res) => {
console.log(res);
})

Spring boot does not receive headers from react js

I'm implementing a ReactJs applications. I am using axios to invoke server side services built using Spring Boot. I need to send the header "Authorization: Bearer token-value". This is the client side code:
var options = {
withCredentials: true,
headers: {'Authorization': 'Bearer token-value'}
};
axios.post('http://localhost:9090/services/list', null, options)
.then((data) => {
console.log(data);
})
.catch((error) => {
console.error(error);
});
This is the Spring Boot controller:
#RestController
public class ServiceController {
private static final String AUTHORIZATION_HEADER_NAME = "Authorization";
private static final String BEARER = "Bearer ";
private static String getToken(HttpServletRequest request) {
String header = request.getHeader(AUTHORIZATION_HEADER_NAME);
if (header == null || header.trim().equals("")) {
return null;
}
header = header.trim();
if (!header.startsWith(BEARER)) {
return null;
}
return header.substring(BEARER.length()).trim();
}
#GetMapping
#RequestMapping(value = "/services/list", produces = "application/json", method = RequestMethod.POST)
public ResponseEntity<?> getTargets(HttpServletRequest request, HttpServletResponse response) {
String token = getToken(request);
if (token == null) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
DTOObject obj = goForTheBusinessObject(token);
return new ResponseEntity<>(obj, HttpStatus.OK);
}
}
This is the CORS configuration
#Configuration
public class RestConfig {
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("POST");
config.addAllowedMethod("GET");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PUT");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
If I invoke the service using curl I got the expected response:
curl -X POST -H "Authorization: Bearer token-value" http://localhost:9090/services/list
If I invoke the service using post man, again I got the right answer.
But when I executed the ReactJS application, the server never receive the "Authorization" header.
Somebody help me please !!
You are facing CORS issues, Implement this class to resolve this-
#Component
public class CorsFilter implements WebFilter {
#Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
if (exchange != null) {
exchange.getResponse().getHeaders().add("Access-Control-Allow-Origin", "*");
exchange.getResponse().getHeaders().add("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS");
exchange.getResponse().getHeaders().add("Access-Control-Allow-Headers",
"DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range");
exchange.getResponse().getHeaders().add("Access-Control-Max-Age", "1728000");
if (exchange.getRequest().getMethod() == HttpMethod.OPTIONS) {
exchange.getResponse().getHeaders().add("Access-Control-Max-Age", "1728000");
exchange.getResponse().setStatusCode(HttpStatus.NO_CONTENT);
return Mono.empty();
} else {
exchange.getResponse().getHeaders().add("Access-Control-Expose-Headers", "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range");
return chain.filter(exchange);
}
} else {
return chain.filter(exchange);
}
}
}
For more info on CORS visit this
Update: For scanning the component you can do following-
#ComponentScan(value = "com.pck", // cors filter package
useDefaultFilters = false)
public class MainClass {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.
run(MainClass.class, args);
}
}

Spring-boot angularjs satelizer cors filter

Have a problem with CORS filter, i think.
Because when i send request with Authorization header by Intellij Idea REST Tools, my filter catch a Authorization header.
But when i try to send request from client side from another server, filter does not see my header(return null).
I`m using spring boot, angularjs, salelizer and JWT for build token.
Params for building token on server side.
private static final JWSHeader JWT_HEADER = new JWSHeader(JWSAlgorithm.HS256);
private static final String TOKEN_SECRET = "Bearer";
public static final String AUTH_HEADER_KEY = "Authorization";
My Auth filter
public class AuthFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String authHeader = httpRequest.getHeader(AuthUtils.AUTH_HEADER_KEY);
if (StringUtils.isBlank(authHeader) || authHeader.split(" ").length != 2) {
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, AUTH_ERROR_MSG);
} else {
JWTClaimsSet claimSet = null;
try {
claimSet = (JWTClaimsSet) AuthUtils.decodeToken(authHeader);
} catch (ParseException e) {
httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, JWT_ERROR_MSG);
return;
} catch (JOSEException e) {
httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, JWT_INVALID_MSG);
return;
}
// ensure that the token is not expired
if (new DateTime(claimSet.getExpirationTime()).isBefore(DateTime.now())) {
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, EXPIRE_ERROR_MSG);
} else {
chain.doFilter(request, response);
}
}
}
#Override
public void destroy() { /* unused */ }
#Override
public void init(FilterConfig filterConfig) throws ServletException { /* unused */ }
}
My CORS filter in Web Mvc config file
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.addExposedHeader("Authorization");
config.addExposedHeader("Content-Type");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
My security configure
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,"**").permitAll().and().authorizeRequests()
.antMatchers( "/index","/api/**", "/auth/**", "/js/**", "/css/**", "/html/**")
.permitAll().anyRequest().authenticated();
My cliend side configs
function configHttp($httpProvider, $authProvider){
console.log("sdfd");
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
$httpProvider.defaults.headers.common["Accept"] = "application/json";
$httpProvider.defaults.headers.common["Content-Type"] = "application/json";
var token = sessionStorage.getItem("satellizer_token");
if (token && $authProvider.httpInterceptor) {
token = $authProvider.authHeader === 'Authorization' ? 'Bearer ' + token : token;
$httpProvider.defaults.headers.common[$authProvider.authHeader] = token;
}
}
function configAuth($authProvider) {
$authProvider.httpInterceptor = function() { return true; };
$authProvider.baseUrl = 'http://localhost:8080';
$authProvider.loginUrl = '/auth/login';
$authProvider.signupUrl = '/auth/registration';
$authProvider.tokenName = 'token';
$authProvider.storageType = 'sessionStorage';
$authProvider.authToken = 'Bearer';
$authProvider.authHeader = 'Authorization';
}
There are a few options described here.
One option would be to annotate your controller method or class with #CrossOrigin.
If you want global config, you could add a new bean. I took this from the Spring doc listed above and modified it so that the mapping is /*. You can modify that path to be suitable for your application. According to the javadoc all origins will be allowed by default.
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/*");
}
};
}

Response for preflight has invalid HTTP status code 403

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!
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()
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() {}
}
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);
}
}
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.

Resources