I'm getting this in the console when I'm trying to update data in my database, using spring mvc and ajax from my jsp.
http://localhost:8080/my_project/activerutilisateur/user 405 (Méthode Non Autorisée)
See my code below:
DAO
public Utilisateur updateUtilisateur(Utilisateur utilisateur) {
sessionFactory.getCurrentSession().update(utilisateur);
return utilisateur;
}
Controller
#RequestMapping(value="/activerutilisateur/{username}", method=RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public Utilisateur activerUtilisateur(#PathVariable String username, #RequestBody Utilisateur utilisateur) {
utilisateur = service.getUtilisateurById(username);
utilisateur.setEnable(true);
return service.updateUtilisateur(utilisateur);
}
Ajax request
<script>
function activerUtilisateur(username) {
var user = {"username" : username}
$.ajax({
contentType: 'application/json',
type: 'POST',
url: 'activerutilisateur/',
data : JSON.stringify(user),
error: function(xhr,error,textStatus){
console.log(textStatus);
},
complete: function(data) {
console.log(data);
console.log('complete done');
},
success: function(data) {
alert('success done');
}
});
}
</script>
It's the only method which doesn't work in the project
Someone could please help me to find what I did wrong?
Thanks
I finally found what's wrong here :
https://matthewbusche.com/blog2/2016/08/06/using-csrf-with-spring-security-and-ajax-calls/
It's due to csrf
Your controller is a POST method, but you are reading the pathVariable, instead of any request body, normally in POST call you need to send Payload to your controller. And in Ajax, you are passing
url: 'activerutilisateur/'+username ----> for PathVariable
data: {'username' : username} ----> There is no requestBody in Controller for this payload.
You should update your controller to have a Request Body as an Argument.
Edited: I ran below code and its working fine in my local machine
JSP/JS Code:
<script>
function activerUtilisateur(username) {
var user = {
"username" : username
}
$.ajax({
contentType: 'application/json',
type: 'POST',
url: 'activerutilisateur/',
data : JSON.stringify(user),
error: function(data){
console.log('Motif erreur : '+data);
},
complete: function(data) {
console.log('complete done');
},
success: function(data) {
console.log('success done');
}
});
}
</script>
Controller Code:
#RequestMapping(value = "/activerutilisateur/", method = RequestMethod.POST)
#ResponseBody
public Utilisateur activerUtilisateur(#RequestBody Utilisateur user) {
service.activerUtilisateur(username);
return user;
}
Model code:
public class Utilisateur {
private String username ;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
Also, it seems you have enabled csrf protection, so check Sending CSRF Token from JS for sending csrf token in the call to the controller.
I suppose that this is your Utilisateur model class :
public class Utilisateur {
private String username ;
// getter & setter
}
In your Controller :
#RequestMapping(value="/activerutilisateur/", method=RequestMethod.POST)
#ResponseBody
public Utilisateur activerUtilisateur(#RequestBody Utilisateur user) {
return service.activerUtilisateur(user.getUsername());
}
In your Ajax Call :
<script type="text/javascript">
function activerUtilisateur(username){
var user = {
"username" : username
}
$.ajax({
type: 'POST',
url: 'activerutilisateur/',
data : JSON.stringify(user)
error: function(xhr, error, textStatus){
console.log('Motif erreur : '+textStatus);
},
success:function(data){
console.log(data);
}
});
}
</script>
Related
In my code, i have two RequestMapper in my Controller which is designed this way :
#Controller
#RequestMapping("/myHostel.html")
public class HostelController
{
#RequestMapping(method = RequestMethod.GET)
public ModelAndView getText()
{
// do some cool stuff but not the point here
}
#RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public String getMyUrl()
{
String myVariable;
return "{\"myUrl\": \""+myVariable+"\""}";
}
}
And my ajax code :
function openNewTab() {
$.ajax({
url : 'myHostel.html',
type: "POST",
dataType: "json",
beforeSend: function(xhr) {
xhr.setRequestHeader("Accept", "application/json");
},
success : function(response){
console.log(response);
window.open(response.url, '_blank');
},
error: function(jqXHR, exception, errorThrown)
{
console.log(jqXHR.status);
console.log(exception);
console.log(errorThrown);
}
});
}
and my button is kinda like this :
<button tabindex="0" id="mySweetButton" class="btn btn-primary"
onclick="openNewTab();" >
Open a new tab
</button>
And what i get is :
200
parsererror
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
--
I've tried with putting a session variable in the model and a making a window.open(URL_IN_SESSION);
But if you reload the page, it's calling it again.
Making a c:remove on the variable when it's not used to cancel this problem but to no avail.
I have to get a variable from my ModelView after some previous call and open it in ajax (or javascript whatever as long as it works) to have my main page and my new tab with the custom URL.
If anyone has a idea on what i'm doing wrong ? (I need a custom URL made in my controller by previous GET call with user choices.)
Thank you for reading !
Solved by making just another GET requestMapping using no parameters and with value = ("/myHostel.html/getMyUrl.html")
One of the problem was the filters that only allowed .html url for the mapping.
The other was the JSON, just using :
#RequestMapping(method = RequestMethod.GET, value = "/getUrl.html")
public ResponseEntity<String> sendUrl()
{
return new ResponseEntity<>(getMyUrl(), HttpStatus.OK);
}
And parsing the return in ajax :
function openNewTab() {
$.ajax({
url : 'myHostel.html/getUrl.html',
type: 'GET',
dataType: 'text',
success : function(data){
window.open(data, '_blank');
}
});
}
And it solved the problem.
I have a ResponseEntiy that receives a comment:
#RequestMapping(value="/save-comment", method=RequestMethod.POST)
#ResponseBody
public ResponseEntity<?> saveComment(#RequestParam("name") String comment, #RequestParam("id") long id) {
SiteUser user = authController.getUser();
String cleanedCommentBody = htmlPolicy.sanitize(comment);
StatusUpdate status = statusUpdateService.getOneById(id);
Comment createdcomment = new Comment();
createdcomment.setCommentdate(new Date());
createdcomment.setCommenttext(cleanedCommentBody);
createdcomment.setStatusUpdate(status);
createdcomment.setSiteUser(user);
commentService.createComment(createdcomment);
return new ResponseEntity<>(null, HttpStatus.OK);
}
The code in my JSP works fine.... it sends the values to my Controller method and the method receives it, process the information and saves the new comment in the database, but after that, showing the same page.... it gives me the error. But other POST request I have work fine.
http://192.168.160.128:8080/viewonestatus/58
Exception: org.springframework.web.HttpRequestMethodNotSupportedException:
Request method 'POST' not supported
Failed URL: http://192.168.160.128:8080/viewonestatus/58
Exception message: Request method 'POST' not supported
The AJAX snippet is that gives an ok code is:
.....
<c:url var="saveComment" value="/save-comment" />
.....
function saveComment(text) {
//alert("El texto es...text " + text);
editComment(text, "${status.id}", "${saveComment}");
}
function editComment(text, id, actionUrl) {
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
jqXHR.setRequestHeader(header, token);
});
$.ajax({
'url' : actionUrl,
data : {
'name' : text,
'id' : id
},
type : 'POST',
success : function() {
alert("Ok");
},
error : function() {
alert("error");
}
});
}
I am new in spring security and I have several question on this topic.
Can I use regular html files or I need to create jsp file for the login page ?
and if I don't want to create form but only few fields is it ok ?
This is my HTML in JS
createContent: function(controller){
this.emailInput = new sap.m.Input('emailInput', {
liveChange: function(event) {
}
})
var passwordInput = new sap.m.Input('passwordInput', {
type: 'Password',
liveChange: function(event) {
}
});
return layout;
},
this is the controller
$.ajax({
type: 'POST',
url: SERVER_URL + '/login',
data : 'j_username=' + myUserName + '&j_password='+ myPassword,
success: function(result) {
...
}
})
this is the servelet
#RestController
#RequestMapping("/login")
#SuppressWarnings("unchecked")
public class AuthenticationController {
#RequestMapping(method = RequestMethod.POST)
#ResponseBody
public String login(#RequestParam(value="j_username", required=true) String email,
#RequestParam(value="j_password", required=true) String password)
{
try {
....do logic and create resultList
return gson.toJson(resultList);
}
catch (Exception e) {
return e.toString();
}
finally {
em.close();
}
}
You can use simple HTML for login page as well. Ultimate aim is to call post service (bydefault /j_spring_security_check) from client page (html or jsp), as long as this is valid, you may call from any extension.
I have the this code to post json to a controller.
The problem is that the credentials object does not get populated with the posted values.
How do I change this code so that it works?
I see in Fiddler that the request is being posted correctly.
[HttpPost]
public JsonResult Authenticate(CredentialsModel credentials)
{
return Json(credentials);
}
[DataContract]
public class CredentialsModel
{
[DataMember(Name = "user")]
public string User;
[DataMember(Name = "pass")]
public string Pass;
}
$.ajax({
type: "POST",
url: "/login/authenticate",
cache: false,
contentType: "application/json; charset=utf-8",
data: '{"user":' + JSON.stringify($('#username').val()) + ',"uass":' + JSON.stringify($('#userpass').val()) + '}',
dataType: "json",
timeout: 100,
success: function (msg) {
},
complete: function (jqXHR, status) {
if (status == 'success' || status == 'notmodified') {
var obj = jQuery.parseJSON(jqXHR.responseText);
}
},
error: function (req, status, error) {
}
});
The default MVC model binder only works with properties. Your CredentialsModel is using fields. Try changing them to properties. You can also remove the annotations.
public class CredentialsModel
{
public string User { get; set; }
public string Pass { get; set; }
}
Also, as pointed out by Sahib, you can create a Javascript Object and then stringify it, rather than stringifying each one. Although that doesn't appear to be the problem in this case.
data: JSON.stringify({
User: $('#username').val(),
Pass: $('#userpass').val()
})
Try chaning your data like this :
$.ajax({
.................
//notice the 'U' and 'P'. I have changed those to exactly match with your model field.
data: JSON.stringify({User: $('#username').val(),Pass: $('#userpass').val()}),
.................
});
this is my ajax post code on Default.aspx's source side:
$.ajax({
type: "POST",
url: "Default.aspx/f_Bul,
data: "{_sSKodu:'4'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
$("#" + div).html(msg.d);
$("#" + div).show();
}
}
)
and this is my function which is on the Default.aspx.cs
protected void f_Bul(string _sSKodu)
{
Select s = new Select(_sSKodu);
}
I want send parameter to f_Bul. but i cant post that data.
where is my mistake?
You need to decorate your method with the [WebMethod] attribute, and it must be static. It might have to be public and return a string as well, not 100% on that though.
[WebMethod]
public static string f_Bul(string _sSKodu)
{
Select s = new Select(_sSKodu);
}
I couldn't get it to work with .aspx, so I went to .asmx and this is how I finally got it ot work:
[System.Web.Script.Services.ScriptService]
public class getData : System.Web.Services.WebService
{
[WebMethod]
[ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]
public string finalize(String Number)
{
return "{'result':'success'}";
}
}
I also had to put a script manager on my .aspx page, but it finally worked.