I have a website, backend is in spring, frontend is in React. I save a cookie on backend using
Cookie cookie = new Cookie("userId", testDTO.getId());
userCookie.setPath("/");
response.addCookie(userCookie);
But when react posts request on the controller, my browser doesnt get that cookie. Storage in firefox is just empty.
Frontend code:
const requestOptions = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
name: username,
stayLogged: false
})
};
fetch('http://localhost:8080/health-check/post',requestOptions)
.then(response => response.json())
.then(data =>{console.log(data);})
I fixed it. Just added to the post mapping in the controller
#CrossOrigin(origins = "http://localhost:3000", allowCredentials = "true")
Related
I am using Vue.js, axios and Spring.
On the page I have the following axios code
axios({
method: 'post',
url: '/user/info',
params: {
'_csrf' : document.getElementById('csrf_id').value,
'name' : 'job',
'age' : '25',
},
headers: {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json'}
});
And on the server I have a receiving method like this
#Controller
#RequestMapping("/user")
public class UserInfo {
#ResponseBody
#PostMapping(value = "/info", consumes = "application/x-www-form-urlencoded", produces = "application/json" + ";charset=utf8")
public String info(#RequestParam(value = "name") String name, #RequestParam(value = "age") String age) {
System.out.println(name);
System.out.println(age);
return "ok";
}
}
Axios makes a request to the server, but the server returns a 415 response.
The request headers are missing the application/x-www-form-urlencoded content type. I suspect the problem lies precisely in this.
Tell me, what am I doing wrong?
HttpMethod Post is a method of writing and transmitting data in the request body.
In your case, you put data through params. If you execute code as you write, data will be sent such as /user/info?_csrf=value&name=job&age=25 and there will be no data in the request body.
To get the response you want, you can modify it as below.
axios({
method: 'post',
url: '/user/info',
data: '_csrf=csrf&name=job&age=25',
headers: {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json'}
});
change params keyword to data and write data like querystring.
After spending more than half a day still not able to get down to whats wrong with the following:
Trying to send form data from NodeJSto Spring Rest API.
Node JS:
var inputData = { base : req.body.base, test : req.body.test }
var queryParams = {
host: '127.0.0.1',
port: 8080,
path: '/start',
method: 'POST',
headers: {'Content-type': 'application/json'},
body: inputData //Used JSON.stringify(inputData) - didn't work
};
Using http module to send request:
var req = http.request(queryParams, function(res) {
//do something with response
});
req.end();
Spring Rest:
#RequestMapping(value = "/start", method = RequestMethod.POST, consumes = "application/json")
#ResponseBody
public String startApp(#RequestBody String body) {
System.out.println(body);
return "{\"msg\":\"Success\"}";
}
Using postman I am able to see the same inputData going through the Rest. But when sent from NodeJS, all I see is
{
timestamp: 1506987022646,
status: 400,
error: 'Bad Request',
exception: 'org.springframework.http.converter.HttpMessageNotReadableException',
message: 'Required request body is missing: public java.lang.String ApplicationController.startApp(java.lang.String)',
path: '/start'
}
Using spring-boot-starter parent in the maven.
Am I missing anything here? Any suggestions would be greatly appreciated!
I don't think that you put request body in queryParams will work.
You can try using req.write() to write data to request body as follows:
...
req.write(inputData);
req.end();
...
#CrossOrigin(origins = "http://localhost:3000")
#GetMapping("")
public ResponseEntity<List<ToDoItemViewModel>> loadCategoriesByName(#RequestParam(required = false) String name)
{
List<ToDoItemViewModel> allItemsByCategoryName = toDoItemService.getAllItemsByCategoryName(name);
return new ResponseEntity<>(allItemsByCategoryName, HttpStatus.OK);
}
How can i pass just a primitive type to the controller, here is how my $.ajax looks like
$.ajax({
method: 'GET',
url: "http://localhost:8080/todItems",
contentType: 'application/json',
crossDomain: true,
data: 'Work',
success: (resp) => {
console.log(resp)
},
error: (resp) => {
console.log(resp);
}
})
Now when i debug it, it indeed sends the request to this controller, but the String name is always null for some reason, can you just show me what i have to adjust in my ajax request, it's probably something in the data field.
You are using GET Request with request params(#RequestParam annotation).
#RequestParam means that param in request pass across url, like this;
http://localhost:8080/todItems?name=Work
So, you just need to move data to url params.
If you prefer send data across request body, please do not use GET method, use POST instead. Many web servers are not supporting request body in GET Requests
I am having a problem with passing a cookie while trying to make subsequent requests with AJAX to my Spring MVC controller.
For e.g. I have a /login endpoint to which I pass some JSON via POST method and it sets the cookie. I see the cookie in the firebug:
As you can see it is there. I am creating a cookie like this:
NewCookie cookie = new NewCookie(new Cookie(SECURITY_TICKET, encodedTicket, configKey, null), null, (int) TimeUnit.MINUTES.toSeconds(expireTime), expireTimeDate, false, false)
And setting it to HTTP headers:
httpHeaders.add(HttpHeaders.SET_COOKIE, cookie.toString());
Then these headers are being added to ResponseEntity like this:
ResponseEntity entity = new ResponseEntity<>(this.entity, this.httpHeaders, this.status)
And this response entity is returned. My conroller's methods are all REST based.
So then I am trying to call the other (/search) endpoint after successful login which functionality is expecting the cookie and it obviosly fails because for some reason cookie is not being passed back.
My AJAX calls looks like this:
$(function () {
$.ajax({
url: 'http://localhost:8080/dev-citigroup-citi/login',
type: 'POST',
dataType: 'json',
data: '{ "username": "client1", "password": "*******", "platform": "iOS", "UUID": "321321321", "application": "CitiReach", "applicationVersion": "1.0" }',
success: function (data, status, xhr) {
$.ajax({
url: 'http://localhost:8080/dev-citigroup-citi/search/eventattendee?q=*:*&start=0&rows=1&wt=json&indent=true',
type: 'GET',
xhrFields: { withCredentials:true },
success: function (data, status, xhr) {
console.log(data);
},
error: function (jqXHR) {
console.log(jqXHR);
}
});
},
error: function (jqXHR) {
console.log(jqXHR);
}
});
});
As I mentioned the /login is OK but the other call fails. I am adding xhrFields: { withCredentials:true } which should be including the cookie in the /search request but for some reason it is not.
I also have CORS being set up correctly:
Access-Control-Allow-Origin: http://localhost:63342
Access-Control-Allow-Credentials: true
http://localhost:63342 is the origin where the request comes from, it is configured in the CORS headers.
Any idea what might be wrong here?
I found the solution, so rather than having xhrFields: { withCredentials:true } on the method level, I've put it globaly:
$.ajaxSetup({
xhrFields: {
withCredentials: true
}
});
And cookie is passed now within the subsequent requests. No idea why it doesn't work on method level, maybe a bug in jquery...
jQuery version I was using: 2.1.3
Maybe this will help someone in future.
I have a problem in my spring boot app with the csrf token.
I have a form where I can edit a Person. A Person can have
Let us now imagine that the person has a car and enter this and store it. The next time he wants to delete this car and enter another one. I have created that so that there is a list of all of his cars -- he has the option to remove this from the list. Now I'm starting from these pills and want to send with the corresponding ID to the server a POST. When I try I get a 403 forbidden and I have no idea why.
If I change from POST to GET, then it works.
My JavaScript (taken from this site: http://docs.spring.io/autorepo/docs/spring-security/4.0.0.CI-SNAPSHOT/reference/htmlsingle/#the-csrfmetatags-tag)
var csrfParameter = $("meta[name='_csrf_parameter']").attr("content");
var csrfHeader = $("meta[name='_csrf_header']").attr("content");
var csrfToken = $("meta[name='_csrf']").attr("content");
// using JQuery to send a non-x-www-form-urlencoded request
var headers = {};
headers[csrfHeader] = csrfToken;
$.ajax({
url: "./delete/car",
type: "GET",
headers: headers,
});
$.ajax({
url: "./delete/car",
type: "POST",
headers: headers,
});
My controller methods:
#RequestMapping(value = "/{login}/delete/car", method = RequestMethod.GET)
public ModelAndView delete(#PathVariable("login") final String login) {
System.out.println("Stop");
return new ModelAndView("redirect:" + WebSecurityConfig.URL_PERSONS_OVERVIEW);
}
#RequestMapping(value = "/{login}/delete/car", method = RequestMethod.POST)
public ModelAndView deleteInstEmp(#PathVariable("login") final String login) {
System.out.println("Stop");
return new ModelAndView("redirect:" + WebSecurityConfig.URL_PERSONS_OVERVIEW);
}
Any suggestions?
Thanks in advance.
OK, after strugglin with all that, I get the following result.
I added the fail method to the Ajax construct and get the following message:
"Failed to execute 'setRequestHeader' on 'XMLHttpRequest': '${_csrf.headerName}' is not a valid HTTP header field name."
the official spring site advises that you have to put this: <sec:csrfMetaTags /> or from other sources, this: <meta name="_csrf" th:content="${_csrf.token}"/> in your html file.
After this, you should be able to access these attributes in your JavaScript, but in my case I get undefined and ${_csrf.headerName}.
A last try was to take the value from the hidden value (chapter 24.5: http://docs.spring.io/autorepo/docs/spring-security/4.0.0.CI-SNAPSHOT/reference/htmlsingle/#the-csrfmetatags-tag).
Now, I have the following:
$(function () {
var token = $("input[name='_csrf']").val();
var header = "X-CSRF-TOKEN";
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(header, token);
});
});
$.ajax({
url: "./delete/car",
type: "POST",
success:function(response) {
alert(response);
}
});
With this it works like a charm.
Another way, you can use the following code:
$.ajax({
url : './delete/car',
headers: {"X-CSRF-TOKEN": $("input[name='_csrf']").val()},
type : 'POST',
success : function(result) {
alert(result.msgDetail);
}
})
I suggest you first check if a valid csrf token and the header have been generated using chrome debugger. If not, then have you added the <sec:csrfMetaTags /> in the <head>?(you will need to import the spring security taglibs). If using Apache tiles, you will have to add this at the <head> section of the template file being used for the view.
If the token is not empty, then in your security-context/configuration file, check if you have disabled csrf security by any chance. By default it is enabled and needs to be for this process to work.