2009-12-22 20 views
9

Tengo un proceso de pago para un carrito de compras que actualmente almacena datos de tarjetas de crédito en la sesión para recuperarlos una vez que el usuario finaliza la compra. El proceso de compra está configurado de tal manera que el usuario ingresa la tarjeta de crédito, ve una página de confirmación y luego finaliza el pedido. Las acciones de confirmación y finalización son las dos únicas acciones que necesitan acceso a los datos de la tarjeta de crédito y para estar seguro de que todas las demás acciones deben descartarlo.ASP.NET MVC - Almacenamiento temporal seguro de datos de tarjetas de crédito

A falta de hacer la reflexión en un controlador base para comprobar la acción actual que está llamando el usuario, no puedo pensar en una forma elegante de descartar los datos en las solicitudes no permitidas. Además, si el usuario no realiza otra solicitud después de ingresar los datos, permanecerá en la sesión hasta que vuelva al sitio web, siempre que eso suceda. Una sugerencia que me ofrecieron fue encriptar los datos en un campo oculto y confiar en el boleto SSL para evitar el almacenamiento en caché del marcado. Parece un enfoque bastante seguro, pero no me gusta la idea de cifrar o no los datos de la tarjeta de crédito en una ubicación accesible para el usuario. El almacenamiento en la base de datos se ha eliminado porque el cliente no desea que se guarden los datos de la tarjeta de crédito.

¿Cuál es el enfoque ideal para persistir temporalmente datos confidenciales como la información de la tarjeta de crédito en más de una solicitud de página?


Tal vez alguien me puede decir si este es un enfoque suficiente. He configurado mi Carrito de Compras que está almacenado en la sesión para tener un Guid único generado cada vez que se actualiza el objeto y ese Guid se utiliza como clave para cifrar y descifrar los datos de la tarjeta de crédito que estoy serializando con el Rijndael algorithm. Los datos de la tarjeta encriptada se pasan luego al usuario en un campo oculto y se deserializa luego de hacer clic en finalizar. El resultado final es una cadena muy parecido a éste:

VREZ%2bWRPsfxhNuOMVUBnWpE%2f0AaX4hPgppO4hHpCvvwt%2fMQu0hxqA%2fCJO%2faOEi%2bX3n9%2fP923mVestb7r8%2bjkSVZDVccd2AJzCr6ak7bbZg8%3d 

public static string EncryptQueryString(object queryString, Guid encryptionKey) 
{ 
    try 
    { 
     byte[] key = Encoding.UTF8.GetBytes(ShortGuid.Encode(encryptionKey).Truncate(16));//must be 16 chars 
     var rijndael = new RijndaelManaged 
          { 
           BlockSize = 128, 
           IV = key, 
           KeySize = 128, 
           Key = key 
          }; 

     ICryptoTransform transform = rijndael.CreateEncryptor(); 

     using (var ms = new MemoryStream()) 
     { 
      using (var cs = new CryptoStream(ms, transform, CryptoStreamMode.Write)) 
      { 
       byte[] buffer = Encoding.UTF8.GetBytes(queryString.ToString()); 

       cs.Write(buffer, 0, buffer.Length); 
       cs.FlushFinalBlock(); 
       cs.Close(); 
      } 
      ms.Close(); 
      return HttpUtility.UrlEncode(Convert.ToBase64String(ms.ToArray())); 
     } 
    } 
    catch 
    { 
     return null; 
    } 
} 
+0

Acerca de su actualización: encriptar la información de la tarjeta no es el obstáculo, es difícil garantizar que todas las piezas de la solución sean seguras. Por ejemplo, ¿dónde está almacenando el GUID utilizado como clave? ¿Alguien más tiene acceso al servidor que genera los GUID? (Esto puede hacer posible que alguien adivine los GUID). ¿Está utilizando el mismo GUID por sesión o por duración de la aplicación? – meklarian

+0

Además, el bloque catch {} da un poco de miedo. ¿No sería mejor devolver una cadena vacía allí? – meklarian

+0

Buen punto en ToString() meklarian. Copié eso de otro lado sin mirar demasiado de cerca. El Guid se genera una vez por usuario por sesión, por lo que creo que conseguir un Guid del usuario sería bastante complicado. –

Respuesta

10

La mejor manera de manejar esta situación es el uso de un servicio de pago que admite dos cosas:

  1. Autorización -> semántica de terminación.
  2. Tokenization

autorización le permitirá reservar la cantidad de carga designada en el momento en que se reciba la información de pago, y luego avance permite que se comprometa el cargo al lote de pagos una vez que el pago/orden se confirma. Si se cancela el pedido, no tiene que emitir una Finalización y también puede intentar eliminar la autorización.

En cuanto a la tokenización, la mayoría de las puertas de enlace que admiten el método antes mencionado para gestionar pagos devolverán un token, generalmente una identificación numérica, para la transacción pendiente.El token puede manejarse como lo desee, ya que no tiene valor para nadie que no tenga acceso a sus credenciales de autenticación en la puerta de enlace. Esto transfiere la carga de seguridad a la puerta de enlace también.

Almacenar la información de la tarjeta de crédito real de cualquier manera que no sea la retransmisión de una carga a una puerta de enlace/procesador es una mala idea. Más allá de los problemas de seguridad de los datos, esto también colocará su aplicación en el alcance de almacenamiento de información de la tarjeta PCI/PABP, lo que implica una gran cantidad de reglas y regulaciones que no querrá tratar en su aplicación. Creo que también hay una tarifa regulatoria que se impondrá el próximo año para las aplicaciones compatibles, supuestamente $ 10k USD. Es probable que todo esto no valga la pena para usted o su cliente.

Por último, durante el procesamiento intermedio (controladores in-page/event/route), puede usar un SecureString para contener el contenido de los datos hasta que ya no los necesite.

SecureString class (System.Security) @ MSDN

2

Qué acerca del uso TempData? Debería volver a poner el valor en TempData entre las acciones de confirmación y finalización, pero al menos se descartará con cada solicitud. Tenga en cuenta que TempData utiliza la sesión para el almacenamiento, por lo que no es más seguro mientras se almacena, pero sí tiene la función de eliminación automática. Yo también me resistiría a guardar el número en la página. Sospecho que esto viola las reglas de PCI.

Otra alternativa sería almacenar la información de la tarjeta en una base de datos. Si lo conserva en absoluto en su aplicación, probablemente ya esté sujeto a las reglas de PCI de todos modos. Almacenarlo en el DB lo hace más fácil ya que solo necesita ingresar el ID de la tarjeta de facturación en las solicitudes subsiguientes. Esto podría ser fácilmente en un campo oculto.

+0

Entiendo que TempData solo almacenó datos durante los redireccionamientos. Si lo configuro en mi Controller, presento una Acción, luego proceso una solicitud para una segunda acción. TempData se ha ido en ese punto, ¿pensé? –

+0

TempData se almacena entre dos solicitudes en la misma sesión. Se usa mejor para los redireccionamientos, pero no hay restricciones técnicas para ello. El marco no sabrá que una solicitud entrante es el resultado de una redirección o alguna otra acción. – tvanfosson

+0

Si ese es el caso, entonces parece un enfoque limpio. –

0

¿En qué país se basa en esto y lo que las compañías de tarjetas de crédito están involucrados? El enfoque completo de enviar números completos de tarjetas de crédito al cliente (en cualquier forma) hace que parezca que no se ha ocupado del manejo profesional de tarjetas de crédito (no lo tome como un insulto).

¿Está su cliente dispuesto a entrar en conflicto con las reglas colectivas de Visa/MasterCard/AMC/Discover para el procesamiento de tarjetas de crédito en línea (PCI DSS)? Su cliente podría terminar siendo excluido por las principales compañías de tarjetas de crédito de realizar transacciones con ellos. En general, es una muy mala idea intentar rodar su propia solución de manejo de tarjetas de crédito en línea: es peor que lanzar su propio algoritmo criptográfico, ya que puede haber multas graves aplicadas a su cliente (letra pequeña en su contrato comercial). Una verdadera solución PCI DSS requiere decenas de miles de dólares en certificaciones y auditorías para garantizar que maneja los datos de las tarjetas de crédito de una manera verdaderamente segura: esta es la razón por la que casi todo el mundo usa un procesador en línea existente.

+0

Sin ofender, tiene toda la razón. El cliente está en los Estados Unidos.Obviamente, no queremos tener que preocuparnos por cumplir con las PCI DSS en absoluto, por lo que el almacenamiento de cualquier información no es ideal. –

+0

La forma más fácil de evitar el almacenamiento de números de tarjeta es utilizar una página de pago alojada y dejar que el proveedor se preocupe por manejar la información de la tarjeta. – tvanfosson

+0

meklarian cubre los detalles del uso de un procesador en línea existente: en general, cuanto más pagas, más procesadores permitirán la personalización para que su página se vea perfecta con el resto de tu sitio. – David

Cuestiones relacionadas