Obfuscate Form Fields Name And Id.


The current way of setting the form fields name and id make it too easy for custom bots.

I suggest some uniq id.

The form could store this uniq ids on the user session.

I disagree, Yii should keep using forms the way they are now. If you choose to make a form public then you are responsible to address the problem with custom bots. Besides your solution might work for a few bots, not all of them.

TIP: use captcha

It definitely doesn’t belong in the core, but an EObfuscatedActiveForm extension (or some such) would be a useful tool.

It’s useful sometimes but if you’ve enabled CSRF tokens, the problem it solves doesn’t exist.

Good points.

So whats the best way, no captcha please, to secure a public form?

Enable CSRF-token for the beginning and see if it’s still an issue.

Enabling CSRF doesn’t prevent bots.


I’m not really for obfuscating. But in some scenarios i find it better to have form field names like “query” instead of “SearchForm[query]”. Consider such a search form which you want to submit via GET. So you want your search results to be shown under a nicer URL like: …?query=myQueryString. As a workaround i now render custom form fields. But then i can’t use the gimmicks of CActiveForm.

I’m not asking for changing the default which is fine for most cases. I just want more freedom for the experienced developer who knows what he is doing.

So the question is: Will there be a way in 2.0 to modify the way, Yii generates form input names?

There’s a way now: Gii templates.

Hmm. Sorry, but i don’t understand. How do Gii templates help me to achieve that:

<?php $form = $this->beginWidget('CActiveForm', ...) ?>

<?php echo $form->textField($model, 'query'); ?>

Gives me a input field with name "query" instead of "SearchForm[query]"?

Well, not with ActiveForm :)

I wonder if it’s not better to let the models generate their form names then. I think, such a change would make form handling more flexible and still can easily provide backwards compatibility. What do you think?

This way the OP could also create obfuscated form inputs if he wants to. This is really an advanced feature, though. The developer must understand the consequences (e.g. problems if he submits several models from 1 form).

I don’t think it’s a good idea to couple form generation and models.

We already do so with form labels. In some way you can even say that a form input name is just another property of a model. So i would not consider this a big break in MVC, rather a pragmatic decision. At least i can not think of a better way to make this more flexible.

I see there’s a similar issue here: https://github.com/yiisoft/yii/issues/470 even though it’s not exactly the same.

Still i disagree with the final conclusion. In my opinion we should not worship MVC as the golden calf if there’s good reason to lessen the strict paradigm slightly. I’d say that this is such a case: the framework forces me to do things the Yii way. If i don’t (=use my custom form inputs) i can’t use many features anymore (e.g. clientside and AJAX based validation). If this can be solved with a minor break in MVC i can’t see, why we should not. This is just an unneccesary restriction.

Mike, can’t you make something similar to the CActiveForm class that enables you to do this?

I think, if I understand you correctly, you’d need:

  • A class for the HTML elements that create attributeName names, instead of Model[attributename] names

  • A class/method then you can use to do something like $model->attributes = MikeCAF::transformGetsOfModel(‘modelName’);

…just brainstorming :)

Of course - but then i’d also have to implement my custom CHtml. That’s not what i’d expect from an easily extensible framework :D

@mike: the active input methods allow you to explicitly specify the ‘name’ attribute. Does this solve your problem?

Thanks, i didn’t think of that. But unfortunately it does not work: If i set the ‘name’ attribute, it also sets this as the ‘id’ of the input element. This breaks the clientside configuration of CActiveForm. For example if i have a model User with field email, the input is <input id=“email” name=“email” but the inline js configures it like {‘id’:‘User_email’.

You also need to set ‘inputID’ in $htmlOptions for the error() method.