I have a problem with an input field in a view called add.ctp. When the input type is set to 'text', the program sequence is normal. But when I change the input type to 'hidden', the following error is displayed:
The request has ben black-holed. Error: The requested address was not found on this server.
mod-rewrite seems activated. Any ideas, what can be the reason for this?
There is no error with your code. CakePHP's Security component checks hidden form fields to prevent tampering by end users:
By default SecurityComponent prevents users from tampering with forms. It does this by working with FormHelper and tracking which files are in a form. It also keeps track of the values of hidden input elements. All of this data is combined and turned into a hash. When a form is submitted, SecurityComponent will use the POST data to build the same structure and compare the hash.
Use FormHelper::unlockField to make a field exempt from this feature:
$this->Form->unlockField('User.id');
This means there is an error with your code. Here is how to create hidden textbox
echo $this->Form->input('field_name', array('type'=>'hidden'));
I think It's because you are using SecurityComponent.
THe component monitor the form integrity, the hidden field shouldn't change from the user and because of that the security component "decide" that the something malicious has been done with the form for example CSRF attack and it prevent the submit. And I believe you are having some JavaScript which change the field value for some reason.
CakePHP 3
Please do not unlock fields/disable CSRF security component for any
particular action. This is important for the form security.
for those who are getting "The request has been black-holed."
,"form tampered error", "you are not authorized to access
that location." or "unexpected field in POST data". It is
mainly due to the CSRF component working as expected.
Disabling or modifying it is not a solution. Instead of disabling, please follow the right approach.
The right way should be as below:
On the Form, Add a hidden field as below.
<?= $this->Form->text('TPCalls.ID',['label' => false, 'class' => 'hidden']); ?>
before AJAX add the field
$("input[name='TPCalls[ID]']").val(event.id);
Then serialise it
var el = $("#xyzForm");
var ajaxTPCalls = el.serializeArray();
$.ajax({
type: el.attr('method'),
async: true,
url: el.attr('action'),
data: ajaxTPCalls,
dataType: "json",
cache: false,
success: function (data) {
toastr.success(data.message, data.title);
},
error: function (jqXHR) {
if (jqXHR.status == 403) {
$("body").html(jqXHR.responseText);
}
}
});
This way you do not disable CSRF or unlock any field. Any suggestions welcome.
Related
I want to implement a validators for my class.
I have two class and one of these is called as array of object in one of my class attribute:
enter image description here
When I try to send the json through postman, the validators tells me that:
must be a number conforming to the specified constraints
This is my ValidationPipe in the main.ts:
app.useGlobalPipes(
new ValidationPipe({
disableErrorMessages: false,
enableDebugMessages: true,
}));
And this is my method in controller:
#UseGuards(AuthGuard)
#Post()
async create(#Body() createDiscussion: CreateDiscussionDto): Promise<Discussion> {
return await this.discussionService.createDiscussion(createDiscussion);
}
How is this possibile if I'm sending the value as number?
Thanks
I expect that the error message will disappear and works when I really send a not number value.
The problem doesn't come from your codebase. It actually comes from your request body.
When you take a deeper look at the JSON from your Postman request, there is a : character inside the property name "like:": while it should just be "like":.
I've been searching and searching, including the many topics here, for a solution to my problem. I've had no luck thus far.
A bit of a backstory: I'm writing an AngularJS app with Drupal 7 as a backend. I'm able to login without problem, save Session Name and Session ID, and put them together for a Cookie header (I had to use this "hack"). Further, if I made a login call in the Postman app, then tried to update the node, it'd work. It makes me think that there's a problem with session authentication, but I still can't figure it out.
That being said, I'm at a roadblock. Whenever I try to PUT to update a node, I get the following error:
401 (Unauthorized : CSRF validation failed)
Now, my ajax call looks like this:
$http({
method: 'PUT',
url: CONSTANTS.SITE_URL+"/update/node/"+target_nid,
headers:{
'Content-Type': CONSTANTS.CONTENT_TYPE,
'Authentication': CONSTANTS.SESS_NAME +"="+CONSTANTS.SESS_ID,
'X-CSRF-Token' : CONSTANTS.TOKEN
},
data: {
(JSON stuff)
}
})
The CONTENT_TYPE is "application/json", the "Authentication" is the band-aid for the Cookie header problem, and the "X-CSRF-Token" is what is (presumably) giving me the problem. SESS_NAME, SESS_ID, and TOKEN are all gathered from the response at Login. I can pull lists made by users on the website, I can pull the list of all of the nodes of a certain type on the website as well. I only run into a problem when I attempt to PUT to update the node.
If I missed any information, let me know and I'll add it!
EDIT: I'm using AngularJS version 1.5.3.
After trying everything else, I followed one of the comments in the thread I linked at the beginning of my original post. They had to comment out a line in Services.module :
if ($non_safe_method_called && !drupal_valid_token($csrf_token, 'services')) {
//return t('CSRF validation failed');
}
It's around line 590, plus or minus a few depending on how much you've messed with the file. I don't like doing it this way, but I can't for the life of me figure out why the token's not working right. It's a temporary fix, for sure, but if someone runs across this with the same problem in the future it'll hopefully help you out!
Instead of removing the line you could also add a true to drupal_valid_token
if ($non_safe_method_called && !drupal_valid_token($csrf_token, 'services',true)) {
return t('CSRF validation failed');
}
I've implemented Heap analytics successfully and i'm seeing data come in.
The way I set a user is:
window.heap.identify(currentUser.id);
window.heap.addEventProperties({ platform_type: 'Web' });
if (currentUser.id) {
console.log('been here');
window.heap.addUserProperties({
'first_name': currentUser.first_name,
'last_name': currentUser.last_name,
'type': currentUser.type,
'country': currentUser.country,
'company_name': currentUser.company_name,
'role': currentUser.role,
'email': currentUser.email
});
}
I'm seeing the Email property data being recorded and associated (Email was a property already pre-defined by Heap), but i'm not seeing any of the other properties.
So, the addUserProperties call is working, but some data is being ignored.
Any idea what i'm doing wrong?
Thanks!
Uri
For anyone with the same problem, for me, the custom properties started appearing after a few hours..
So I made my site live and I am entering into the public realm where people aren't always nice. I just started learning about CSRF and saw that it was something I needed when I made my cakephp 3 site live. As seen here!
I added the csrf component and the security component to my site, but I have 1 major problem. Now, when users want to sign up they can't. I use a custom form for stripe to send payment, but also add a user using ajax to my database. The user gets added first and then the payment is processed and saves the order to the database as well.
According to stripe docs I add the token in a hidden value to the form after I click the submit button and can't help but notice that my new security is not allowing this to happen.
Since I am using ajax to send the post data to my users controller and adding a form input on submit,
How do I check the csrf token and make sure there isn't a security leak without disabling the security for the actions involved?
An example of how this is to be done would be greatly appreciated since examples seem to be lacking for doing this in cakephp 3. It is also hard for me to figure out how everything works since the cakephp 3 automagic adds the tokens to the forms and cookie. I am unsure how/where/what to check.
For pass X-CSRF-Token, use beforeSend parameter in your Ajax request, and define csrfToken value of cookie.
$.ajax({
url: '/foo/bar',
type: 'POST',
dataType: 'HTML',
data: data,
beforeSend: function(xhr){
xhr.setRequestHeader('X-CSRF-Token', csrfToken);
},
})
.done(function(data) {
alert('done !');
});
According to stripe docs I add the token in a hidden value to the form after I click the submit button and can't help but notice that my new security is not allowing this to happen.
Cake's CSRF token would have no effect when POSTing to another site.
Since I am using ajax to send the post data to my users controller and adding a form input on submit,
How do I check the csrf token and make sure there isn't a security leak without disabling the security for the actions involved?
The CSRF token is available in cookie named csrfToken, so read that token in your javascript and set X-CSRF-Token header for your AJAX request. The CsrfCompoment will do the checking.
using js function:
function getCookie(name) {
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");
if (parts.length == 2) return parts.pop().split(";").shift();
}
...
then
$.ajax
({
type: "Post",
url: "URL_HERE",
data: {some_data},
beforeSend: function(xhr){
xhr.setRequestHeader('X-CSRF-Token', getCookie('csrfToken'));
},
success: function (e) {
},
errors: function () {
}
});
I have an input box for a new user to put in a userid. I want to dynamically check if the userid is already taken on-blur. I'm using bootstrap validation for form validation, and I'm having a hard time figuring out how to make it do what I want. In the validation, I have this code currently for userid:
userid: {
container: '#useridMessage',
validators: {
notEmpty: {
message: '*Required'
},
stringLength: {
min:3,
message: 'Username must be at least 3 characters long'
}
}
},
What I want to be able to do in there is call a function I have for the on-blur action:
$scope.userCheck = function () {
userAPIService.getUserDetails($scope.user.username).success( function ( data ) {
if(data.Status == 0){
//make box red and invalid
}
}).error( function ( error ) {
$scope.status = "Error is checking Username availability";
})
}
My backend function is the getUserDetails which is a GET function. I was planning on, as is shown in the code, to check if the userid is a valid one (data.status == 0) already in our system and notify the user after that it is already taken. My desire is to maintain good coding practice and not by pass my bootstrap validation ( which is working well for everything else ) and make both work together, but since bootstrap validation is kind of a black box, I'm not sure how to do this.
Question: How can I get the validation to check some boolean variable, or how can I get the validation to make the backend call and then analyze the result like I want?
Thoughts:
Ideally I'd like to be able to call the onblur function which would set some boolean and then the validation would just look at the validation, but I'm open to any idea to get this right. Thanks
I wonder if creating a custom validation directive would be a good approach. There's a good overview here How to add custom validation to an angular js form, also in the Custom Validation section of the Angular JS Forms documentation. Hope this helps.