2011-06-21 20 views
6

Quería comenzar a usar attr_accessible con mis modelos para detener el problema con la asignación masiva. Entiendo cómo funciona y he investigado tanto como pude.¿Cómo detiene esto la asignación masiva?

Lo que no entiendo es la diferencia entre usar update_attributes (params [: my_form]) o create (params [: my_form]) y configurar los campos uno a uno? ¿No son ambos tan vulnerables?

¿Cuál es la diferencia entre no tener attr_accessible y haciendo esto ...

@model_object = ModelObject.new 
@model_object.create(params[:model_object_params]) 

Y tener attr_accessible y haciendo esto ...

@model_object = ModelObject.new 
@model_object.field1 = params[:model_object_params][:field1] 
@model_object.field2 = params[:model_object_params][:field2] 
@model_object.field3 = params[:model_object_params][:field3] 
@model_object.save! 

¿No son estos dos métodos de creación de la registro tan vulnerable? El hacker/cracker podría enviar una url a ambos métodos y ambos harían lo mismo, ¿no?

¿O el uso de attr_accessible y la actualización de los campos uno a uno hacen algo diferente o de alguna manera se vuelven más seguros?

Ahí es donde todos los métodos que encuentro de usar attr_accessible no tienen ningún sentido para mí. Parece estar haciendo lo mismo de dos maneras diferentes. ¿Qué me estoy perdiendo?

Gracias.

Respuesta

7

En la forma en que lo está haciendo, no impide la "asignación de masas".

"Asignación masiva" es el término utilizado cuando Rails está gestionando la asignación de valores a los atributos en un modelo. Esto se hace típicamente en un controlador, usando los nombres y valores en params.

Cuando se hace la asignación usted mismo, también es "asignación masiva", en cierto modo; pero tienes un control fino sobre qué asignar y qué no en este caso. Por lo tanto, para guardar la escritura de ese código de asignación repetitiva, Rails proporciona attr_accesible - el mismo control, menos código.

Para ver cómo se utiliza:

suponer que un modelo ActivityLog tiene un atributo llamado user_ip_address.

Ahora, user_ip_address es un atributo en el modelo, y podría ser asignados por masa-cesión o por "auto-laminado-masa-cesión".

Pero en ambos casos eso es incorrecto: no desea que la entrada suministrada por el usuario establezca un valor para ese atributo.

En su lugar, siempre desea saber la dirección IP real del usuario y asignar ese valor (ignorando cualquier valor en params). Por lo tanto, excluiría user_ip_address de attr_accessible y, en su lugar, asígnelo.

attr_accessible :all_attributes_except_user_ip_address 

@al = ActivityLog.new(params[:model_object_params]) 
@al.user_ip_address = get_origin_user_ip_address 
@al.save 

Para cualquier información que un usuario no debe ser capaz de cambiar, utilice attr_accessible y excluirlo de la lista.

+0

Oh veo, entonces lo que hago detiene cosas como los campos created_by o creator_id de establecerse, pero sin un control más fino, los campos que se están enviando y estoy asignando podrían tener datos maliciosos. Allí es donde me estaba volviendo loco todos estos ejemplos simplemente asignaron cada campo manualmente en lugar de pasar el hash de parámetros. Ahora veo, gracias. – dsmorey

2

La idea aquí es limitar los parámetros que aceptará para un modelo determinado. Luego puede probar cada uno de ellos con una validación u otro código para asegurarse de que se ajustan a los valores esperados.

Attr_accessible está destinado a limitar la "superficie" de su modelo a lo que pretende aceptar y verificar cuidadosamente. De esta manera se puede ignorar automáticamente un parámetro inyectada como: papeles => "admin" en el caso de agregar esta característica a su modelo

user.update_attributes(params[:user]) 

Desde los papeles atributo no se enumeran en attr_accessible, el intento del usuario para convertirse en una el administrador es infructuoso.

Desea manejar la lógica de validación en un solo lugar (su modelo), en lugar de verificar el valor de cada parámetro en su controlador.

3

La respuesta corta es que impide que field4 se establezca implícitamente.

La diferencia es que sin attr_accessible un hacker podría actualizar un campo que no está en su forma. Con attr_accessible esto imposible.

E.g. Si su modelo de usuario tiene un campo is_admin, un hacker podría tratar de crear un nuevo administrador mediante la publicación:

params[:user][:is_admin] = true 

Si attr_accessible se establece (y, obviamente, no debe contener is_admin) esto es imposible.

Acerca de su ejemplo: si su modelo sólo tiene field1, field2 y field3 y no hay otras columnas de base de datos que desea proteger, no hay necesidad de usar attr_accessible. Espero que esto lo aclare.

Sólo recuerde:

sin ninguna precaución Model.new (params [: modelo]) permite a atacantes para ajustar el valor de cualquier columna de base de datos .

Fuente: http://guides.rubyonrails.org/security.html#mass-assignment

2

La asignación de masa no es algo que prevenga, es algo que usted controla. Es una buena característica, una que hace que las cosas sean más fáciles y más limpias, pero sin algún tipo de habilidad para controlar lo que se establece mediante la asignación masiva, es un potencial agujero de seguridad. attr_accessible, como han mencionado otros, proporciona ese control.

Cuestiones relacionadas