Home » Tecnología

Autenticación basada en formularios y .Net

8 Abril 2010 Tecnología1,433 views One Comment
1 Star2 Stars3 Stars4 Stars5 Stars
Loading ... Loading ...

En esta entrega vamos a crear y configurar el acceso a un directorio privado, con identificación del usuario en un servidor Web.

Esto puede resultar útil cuando no tenemos control sobre el servidor donde alojamos nuestras páginas y queremos hacer una sección privada donde todo el contenido que aparezca en un directorio concreto esté bajo validación de usuarios.

En este tutorial, se mostrarán dos formas de hacerlo con la autenticación de formularios mediante la configuración de los usuarios en el web.config y consulta de usuarios en una base de datos.

Esta autenticación se basa en las cookies de navegador para determinar la identidad de un usuario. Una vez activada en un directorio, no podemos acceder al contenido del directorio salvo que dispongamos de la autenticación adecuada almacenada en una cookie.

2.- ¿Qué necesitamos?

Para activar la autenticación de formularios básica en una aplicación, realizaremos los siguientes pasos:

  • Configurar el modo de autenticación modificando la sección authentication en el web.cofig de la aplicación.
  • Denegar el acceso a los usuarios anónimos en uno o más directorios de la aplicación, mediante la modificación de la sección authorization en los archivos web.config de los directorios privados
  • Creara una página de registro con un formulario que permita la identificación de usuarios.
  • Para la validación contra la base de datos, necesitaremos un servidor de base de datos en el que configuraremos una tabla de usuarios y un procedimiento almacenado.

Para empezar vamos a crear un directorio, PRIVADO, y dentro de este una página default que nos muestre un “HOLA MUNDO PRIVADO” para validar que vemos el directorio en nuestra web.

3.- Modificando el web.config.

Con el directorio privado que hemos creado, y desde el cual podremos colgar todas nuestras herramientas administrativas del site, como el acceso a descargas o imágenes personales, tenemos que realizar una serie de modificaciones en el web.config

En este tutorial no nos vamos a parar en explicar al detalle todas las opciones que se puede usar para la crear un acceso privado, solo nos ocuparemos de las opciones que vamos a usar.

El fichero web.config se encuentra localizado en el directorio raíz de la aplicación web con la que estamos trabajado. Al abrirlo veremos que dentro de la etiqueta system.web se encuentran diferentes opciones, las que ocuparan nuestra atención son las entradas authentication y authorization, ya que son en las que realizaremos las modificaciones.

En el caso de que no exista este archivo web.config podremos crearlo, pero siempre en el raíz de la aplicación.

3.1.- authentication

El archivo web.config contendrá el siguiente código:

<configuration>

  <system.web>
    <authentication mode=”Forms”>
      <forms name=”FormsAuthDB.nevaAuth”
loginUrl=”login.aspx” protection=”All” timeout=”10″ path=”/”>
        <credentials
passwordFormat=”Clear”>
          <user name=”adm”
password=”myadm”/>
        </credentials>

      </forms>
    </authentication>
  </system.web>
<configuration>

Como se puede observar, y parece obvio, el modo de autenticación de nuestro directorio será mediante un formulario, quedando esto reflejado en la propiedad mode=”Forms”

Dentro de la sección forms se definen el funcionamiento de nuestro formulario:

  • name: el nombre de la cookie de navegador que contiene la entrada de autenticación. Si no especificamos uno se llamará .ASPXAUTH
    Recomendamos que si usamos varias aplicaciones en nuestro servidor web se especifique un nombre por aplicación.
  • loginUrl: indicaremos la página a la que se dirigirá al usuario, de modo automático, cuando se precise su identificación. Si no especificamos una página, por defecto se redirige a login.aspx situada en el raíz de la aplicación web.
  • timeout: es el tiempo, en minutos, que la cookie tiene validez, siendo de 30 minutos el valor por defecto.
  • protection: especifica la forma en que se protegen los datos de la cookie. Los valores son All, None, Encryption y Validation, siendo All el valor que se toma por defecto.
    Por omisión las cookies sé encriptan con DES o TripleDES, dependiendo de la capacidad del servidor.

El elemento credentials nos servirá para configurar los usuarios que tendrán acceso a nuestro directorio privado. Esto es útil si no tenemos un listado largo de usuarios y que no queremos o nos es necesario realizar labores de mantenimiento sobre estos.

Este elemento es bastante simple de entender ya que se creará una entrada por cada uno de los usuarios que tendrán acceso a las aplicaciones o elementos descargables que tengamos en nuestra zona privada. En estos configuraremos el nombre de usuario y la password.

Si deseamos disponer de una mayor seguridad, por si algún curioso lograra acceder al servidor y ver las password podríamos encriptarlos utilizando los algoritmos hash SHA1 y MD5, para ello tendríamos que cambiar el valor de passwordFormat por SHA1 o MD5. Pero la forma de encriptar este password y acceder a ellas lo trataremos en otra ocasión.

4.- Configurando el directorio.

Bien, ya tenemos listo el sistema de autenticación, hemos creado el directorio que deseamos hacer privado y preparada una página que nos servirá de bienvenida a la zona privada.

Ahora solo nos falta hacer que este sea privado. Para ello será necesario crear un fichero web.config en el raíz de nuestro directorio privado. En este web.config configuraremos la sección authorization, donde denegaremos el acceso a los usuarios anónimos.

El contenido del web.config será el siguiente.

<configuration>
  <system.web>
    <authorization>
      <deny users=”?”/>
    </authorization>

  </system.web>
</configuration>

Dentro de la sección authorization, se permite las siguientes entradas:

  • deny para denegar usuarios
  • allow para permitir el acceso a usuarios.

Ambas entradas tienen la propiedad users donde podemos especificar:

  • ? todos los usuarios anónimos.
  • * todos los usuarios, tanto anónimos como autenticados.
  • Lista usuarios, se permite especificar un listado de usuarios separados por comas, que tendrán permitido o denegado el acceso según donde se especifique

5.- La página de Login.

Bien ya está todo listo, hemos configurado el directorio, le hemos dado las indicaciones a la aplicación para que nos autentique a los usuarios, hemos definido la autorización del directorio, pero no falta hacer logo, ya que sin esto no veremos nunca ese HOLA MUNDO PRIVADO que hemos preparado.

Pues manos a la obra. Tenemos que crear un formulario web, pero no voy a explicar como hacerlo, se supone que esto ya sabemos hacerlo, pero si no tenemos ganas de golpear teclas, descarga aquí el zip con todo el código.

Este formulario web tendrá los siguientes elementos:

  • Una caja de textos, con su correspondiente título donde pidamos el nombre de usuario.
  • Una caja de texto, y su titulo, donde pidamos la password, esta tendrá la propiedad textmode=Password.
  • Un checbox, con su titulo para que el usuario marque que le recuerde la password en el futuro.
  • Un boto de enviar, y opcional otro de borrar.
  • Una etiqueta para mostrar errores.

Opcionalmente podemos insertar el objeto que nos valide que el usuario a insertado los datos de forma correcta en el formulario.

Ya hemos creado, pintado y dado color a nuestra pantalla de login. Todo al gusto, no me meto.

Como apuntaba al principio de este tutorial, la intención era enseñar dos métodos de validación, una por la configuración de usuarios en el web.config y otra mediante consultas a base de datos.

5.1.- Usuarios en web.config.

Ya se ha explicado donde y como se configurar, si no lo tienes claro pincha aquí. Y ahora tenemos que hacer que cuando el usuario pulse el botón enviar se nos valide y de acceso a este al directorio o nos deniegue el acceso en caso de error.

Para eso incluiremos el siguiente código en el fichero VB de nuestro formulario:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

  ‘Validación con usuarios en el WebConfig.
  If IsValid Then
    If System.Web.Security.FormsAuthentication.Authenticate(tbLogin.Text, tbPassword.Text) Then
      System.Web.Security.FormsAuthentication.RedirectFromLoginPage(tbLogin.Text, chkPassword.Checked)
    Else
      lblError.Visible = True

      lblError.Text = “Nombre de usuario y/o contraseña no validos.”
    End If
  End If
End Sub

Con IsValid comprobamos si el formulario está correcto, esto era opcional.

En la siguiente validación empieza lo duro, ya que con el método Autenticate de la clase FormsAuthentication, hacemos que se localice en el web.config el nombre de usuario y la contraseña introducidas. Devolverá un true o false si lo encuentra o no en la sección credentials.

En el caso de que la respuesta sea errónea, pintamos el correspondiente mensaje de error en la etiqueta reservada para esto.

Si hemos acertado con el usuario y la contraseña entra en juego el método RedirectFromLoginPage, al que le pasamos el usuario y el valor del check para que en el futuro nos pregunte o no por nuestra identificación. Este nos devolverá a la url que hemos intentado acceder dentro de nuestro directorio privado antes de que se nos mostrara la página de login.

5.2.- Usuarios en base de datos.

Ya hemos vista la forma simple de hacer login con nuestros usuarios en el web.config. Ahora lo podemos complicar un poco más utilizando la base de datos, si es que tenemos disposición de hacerlo.

Supongamos que tenemos un SQL Server instalado y que tenemos acceso a el. Tendremos que configurar una tabla, donde tengamos un campo login y otro password como mínimo, el resto de campos a elección. No explicaremos como crear la tabla y el procedimiento almacenado, que reservado para otro tutorial. Si queréis evitar crearlo manualmente, pincha aquí y dentro del zip encontrarás el Script SQL que genera la tabla con esta información mínima y un procedimiento almacenado para buscar el usuario.

Vamos a usar la mismas página aspx que en el ejemplo anterior, pero en esta ocasión añadimos un botón más que nos servirá para llamar a una función diferente.

En esta ocasión necesitaremos importar las siguientes clases para el manejo de base de datos:

Imports System.data
Imports System.Data.SqlClient

Tras pulsar el botón de validar en la Base de datos, se ejecutará el siguiente código:

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
  ’Validación con usuarios en Base de datos.
  If IsValid Then
    If DBAuthenticate(tbLogin.Text, tbPassword.Text) > 0 Then
      System.Web.Security.FormsAuthentication.RedirectFromLoginPage(tbLogin.Text,
chkPassword.Checked)

    End If
  End If
End Sub

Como se puede observar este código es similar al anterior. IsValid nos valida el que el formulario sea correcto

En la siguiente comprobación se hace una llamada a la función, que tendremos que incluir, para realizar la validación contra la base de datos.

La función queda como sigue, se ha de prestar atención a los comentarios para comprender que hace el código:

Function DBAuthenticate(ByVal strUsername As String, ByVal strPassword As String) As Integer
  Dim conMyData As SqlConnection
  Dim cmdSelect As SqlCommand

  Dim parmReturnValue As SqlParameter
  Dim intresult As Integer

  ’Conexión a la base de datos
  conMyData = New
SqlConnection(ConfigurationSettings.AppSettings(“nevaCnnString”))
  ’Preparamos la llamada al Procedimiento Almacenado

  cmdSelect = New SqlCommand(“DBAuthenticate”, conMyData)
  cmdSelect.CommandType = CommandType.StoredProcedure

  parmReturnValue = cmdSelect.Parameters.Add(“RETURN_VALUE”, SqlDbType.Int)
  parmReturnValue.Direction = ParameterDirection.ReturnValue
  ’Asignamos valores a los parámetros del procedimiento almacenado.

  cmdSelect.Parameters.Add(“@username”, strUsername)
  cmdSelect.Parameters.Add(“@password”, strPassword)

  Try ‘Control de errores
    conMyData.Open()
    ’Ejecutamos el Procedimiento almacenado

    cmdSelect.ExecuteNonQuery()
    ’Recogemos el resultado del Procedimiento almacenado.
    intresult = cmdSelect.Parameters(“RETURN_VALUE”).Value
    ’Cerramos conexión
    conMyData.Close()

    If intresult < 0 Then 'Se ha producido error
      lblError.Visible = True
      If intresult = -1 Then ‘Nombre de usuario no valido.
        lblError.Text = “Nombre de usuario no registrado.”
      Else ‘intResult = -2 Error en la password
        lblError.Text = “Password incorrecta.”

      End If
    End If
    Return intresult
  Catch ex As Exception ‘Se produce error en el uso del procedimiento
    lblError.Visible = True
    lblError.Text = “Error al intentar identificar al usuario: “

    lblError.Text &= ex.Message
  End Try
End Function

Sin entrar en detalles de manejo de base de datos, la función prepara el acceso a la base de datos, y el uso del procedimiento almacenado, le asigna los valores nombre de usuario y contraseña a los parámetros del procedimiento y lo ejecuta.

El procedimiento almacenado se encarga de localizar en la tabla en nombre de usuario, y comprobar la password, en caso de ser correctos devuelve el ID correspondiente en la tabla al registro. Este procedimiento controla dos posibles errores, es simple, si no localiza el nombre de usuario devolverá el error -1 y si encuentra el nombre de usuario pero la contraseña no coincide devuelve un -2.

Esta misma función toma como valor el resultado del procedimiento almacenado por lo que al evaluarla desde la pulsación del botón, solamente en caso de que el resultado sea mayor a 0 se redirigirá al usuario a la página o directorio que solicitó, de igual modo que sucedía con la validación del usuario configurado en el web.config, mediante el método RedirectFromLoginPage, que espera recibir nuevamente el nombre de usuario y y el resultado del check que nos evitará la inserción de estos datos en el futuro mediante el control de la cookie.

6.- La prueba.

Si todo está bien y se han seguido los pasos indicados, nuestro directorio estará protegido contra usuarios anónimos. De modo que si llamamos al directorio privado desde le navegador, http://miservidor/privado nos responderá la página de login que indicamos en el web.config, y tras identificarnos correctamente accederemos a la página que habíamos solicitado dentro del directorio privado.

Con esto ya se puede configurar diferentes herramientas administrativas que gestionen el site, o un lugar donde guardes tus fotos personales y que solo quieres que algunos tenga acceso.

7.- Notas.

En la validación por base de datos, no se ha mencionado ya que ase asume que sabemos acceder a base de datos, pero es necesario configurar en el web.config del raíz de la aplicación la cadena de conexión a la base de datos. Esta cadena de conexión es usada en la línea

conMyData = New SqlConnection(ConfigurationSettings.AppSettings(“nevaCnnString”))

¿Cómo decidirse entre configurar los usuarios en el Web.config o en la base de datos? Todo dependerá del número de usuarios que se tiene previsto mantener, si queremos mantener de 3 a 10 usuarios, nos decantaremos por la solución web.config, pero si el número es mayor y encima se permitirá el crecimiento de usuarios la mejor solución es la base de datos

One Comment »

  1. Bueno… se puede seguir el mismo procedimiento usando el login predeterminado de Visual Studio?

Have your say!

Add your comment below, or trackback from your own site. You can also subscribe to these comments via RSS.

Be nice. Keep it clean. Stay on topic. No spam.

You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

buy viagra 32
cheapest cheap viagra
viagra buy it online now
cheap viagra online order viagra now
buy viagra on the internet
buy viagra securely online
cheap viagra canada
buy viagra in australia
buy viagra pharmacy online
buy viagra on-line
buy viagra online in the uk
buy viagra bradenton
buy viagra generic
buy neurontin
fast ways to lose weight
buy online us viagra
spintop games
cheap viagra st
buy viagra internet
buy generic viagra online
buy viagra online cheapest
buy viagra sale
cheap no prescription viagra
cialis online
cheap online viagra viagra
buy viagra in england
discount viagra drug
discount viagra sales
buy viagra online uk
buy viagra cheapest
cheapest price for generic viagra
buy canada viagra
buy viagra in the uk
order viagra or levitra
cheap free viagra
cheapest online viagra
buy pill price price viagra
discount viagra or cialis
cheap kamagra uk viagra
buy viagra in great britain
buy discount viagra online
cheapest price for viagra and cialis
funny tagalog qoutes
cheapest generic substitute viagra
buy viagra us pharmacy low prices
discount viagra brand drug
buy viagra contact us page
cheap generic online viagra
cheap websites for viagra
buy cialis online
buy cialis canada
purchase cialis online
cheap online pill viagra
order viagra online consumer rx
buy online purchase viagra
order viagra international ships
buy viagra in spain
buy cheap viagra on the net
buy lady uk viagra
buy generic viagra img
buy no online prescription viagra
buy discount soma
buy viagra pills
discount viagra sales online
generic levitra
cheap pharmaceutical viagra
deck design
buy lexapro
buy generic viagra online pharmacy online
cheap viagra in uk
buy viagra
discount viagra sale online
buy pharmaceutical viagra
order generic viagra online
buy viagra onlines
viagra buy viagra online
buy cialis no prescription
buy kamagra viagra
buy lipitor
buy viagra cheapest best prices online
cheapest viagra on line
cheap viagra cialis india
buy viagra pill online
cheap viagra discount
order viagra now money
cheap online softtabs viagra
cheap generic viagra no script
reno casino
buy celebrex
buy real viagra online
buy viagra canada
cheapest generic viagra and cialis
cheap viagra viagra
cheap online generic viagra
order cheap viagra
order viagra viagra
free printable baby shower games
buy uk viagra
buy norvasc
viagra canada online pharmacy
cheap soft viagra
cheapest generic price viagra
cheap cialis
cheap cialis online
cheap molde ticket viagra
buy deal online online viagra viagra
cheap online purchase viagra
buy generic viagra
buy viagra online online pharmacy
buy cheap deal pill viagra
buy viagra line
buy cheap site viagra
buy generic viagra pharmacy online
buy cost low viagra
viagra by phone
order viagra buying viagra uk
buy online prescription viagra
viagra by the pill
cheap viagra online uk
viagra by mail canada
buy cheap discount cialis
buy viagra cialis levitra
purchase levitra
cheep viagra
buy viagra in uk
buy cheap viagra
viagra by mail
buy viagra from an online pharmacy
viagra by overnight delivery
buy imitrex
cheap generic substitute viagra
cheapest brand viagra
download bingo
cheap cialis viagra
buy viagra on line
allegra
cheap generic viagra uk
cheap canadian viagra
buy online online pill viagra viagra
buy online sale viagra
buy viagra at safeway
buy real viagra pharmacy online
buy viagra safeway pharmacy
buy online price viagra
cheap india viagra
buy cozaar
cheap generic viagra from usa
buy in uk viagra
buy flomax
free bingo
viagra brazil
order viagra with my checking account
viagra calgary
buy discount levitra
buy online viagra securely
buy viagra online au
aarp games
buy locally viagra
buy viagra online india
purchase levitra online
buy keyword online viagra
buy cymbalta
buy cheap viagra online
buy viagra online paypal
cheap pill viagra
buy viagra in london
cheapest place to buy viagra online
buy viagra overnight
buy pharmacy pill viagra
buy viagra prescription online
cheap herbal viagra viagra
buy viagra 100mg
buy sale viagra
buy viagra 50mg
cheap source viagra
buy viagra low cost
viagra buy in uk online
cheapest viagra on the internet
buy viagra new york
cheap cheap viagra
buy online pill viagra
buy from pharmacy us viagra
buy levitra viagra
cheaper viagra levitra cialis
mecca bingo
order viagra canada
cheap viagra at online pharmacy
viagra canada online
buy cheap generic online viagra
boris vallejo wallpaper
cheap generic viagra
buy online viagra where
cheap deal discount price viagra
cheapest viagra in the uk
cheap viagra india
sandlot games
buy viagra online at cheap price
buy viagra without prescription
order cheap viagra fas
cheap drugs viagra cialas
order viagra
deck designs
cheap viagra in the uk
buy viagra australia
buy real viagra online pharmacy
buy viagra at the best price
discount viagra pills
discount viagra offers
buy diet viagra online
buy viagra all information
cheap levitra online
buy viagra or cilas
buy levitra canada
cheaper viagra levitra apcalis
buy caverta
buy viagra order viagra
cheapest viagra price
buy viagra online paypal vipps
buy viagra online canadapurchase cialis
halloween free ecards
tamiflu
buy get online prescription viagra
cheapest place buy viagra online
discount cialis
cheapest viagra us pharmacy
cheap generic viagra substitutes
buy viagra where
buy viagra without a prescription
how to play poker
viagra and cialis and
buy viagra and cilas
buy pfizer viagra
free printable bridal shower games
cheapest generic viagra and cialis pills
buy viagra online web meds
buy cheap online uk viagra
viagra and cialis cheap
cheap online sales viagra
cheapest viagra world
buy cialis viagra
buy discount generic viagra
viagra buy do nu
order pfizer viagra with mastercard
baccarat strategy
buy cheap online prescription viagra
viagra buy viagra
buy nexium
buy viagra over the counter
cheap prescription viagra without
cheap drug viagra
national bingo night
buy viagra woman
buy site viagra
order uk viagra
cheap viagra discount viagra buy viagra
buy viagra in amsterdam
cheapest viagra uk
buy diovan
order viagra on-line
order cialis online
buy now viagra
buy 100 mg viagra
buy lexapro
cheapest regalis viagra
cheep generic viagra
buy viagra online in uk
little creek casino
order viagra online
order viagra online no rx prescription
order viagra online in wisconsin
buy viagra without prescription pharmacy online
propecia
buy viagra soft tabs
cheap online price price viagra
cheap viagra nz
buy in spain viagra
buy nexium
dice games
buy in online usa viagra
viagra buy general
buy free viagra on internet
buy cialis
buy viagra cheap prices
buy discounted viagra
buy nolvadex
viagra buy ionline
cheap discount cialis
buy cheap viagra online u
teenie files
buy prescription viagra
discount viagra sale
cheap discount viagra viagra
order discount viagra
buy viagra cheap
buy viagra now online
order order viagra
buy kamagra viagra india
cheap generic india viagra
buy viagra from brazil
buy cheap viagra online now
viagra canada price
amazon extract file access architect
cheap viagra bi
buy discount viagra
buy canada in viagra
buy viagra vaniqa prescription
cheapest viagra substitut
buy p viagra
order forms for buying viagra
buy buy sale viagra viagra
buy low price viagra
buy cheapest viagra
buy pill viagra
discount viagra pharmacy online
cheap deal viagra
cheapest uk supplier viagra
viagra by mail order
buy cheap deal viagra viagra viagra
discount viagra overseas
buy viagra online australia
buy viagra online a href
cheap free viagra viagra
cheap herbal viagra
buy viagra powered by phpbb
cheap generic viagra online
buy prescription vaniqa viagra
cheapest prescription viagra
buy now online viagra
viagra canada generic
generic cialis
buy viagra and overseas
buy cheap generic viagra
order site viagra
buy cheap uk viagra
buy isoptin
buy online uk viagra
buy cheap generic viagra online
cheap viagra credit
viagra buy now pay later
buy later now pay viagra
cheapest viagra in uk che
buy viagra online no prescription
online slots
order viagra online a href
discount viagra mastercard
buy cialis now
cheapest uk viagra
order generic viagra
cheap viagra direct
viagra and cialis
buy viagra online discount
buy viagra in bangkok
viagra by money order
cheap levitra
buy viagra online off pharmacy prices
order levitra online
cheap generic overnight viagra
buy viagra in mexico
discount viagra
buy lopressor
buy deal online sale viagra viagra
assassins creed wallpaper
levitra online
order viagra buying viagr
cheapest viagra
buy viagra uk
viagra by mail catalog
cheap meltabs viagra
order viagra now viagra money order
discount viagra online
buy cheap p viagra
viagra buy australia
buy viagra softtabs
buy sildenafil viagra
buy viagra cheaply
discount levitra
buy online sale viagra viagra
buy cheap discount levitra
buy online order viagra
order viagra online uk
viagra brands
order viagra cheap
order viagra usa
buy online pharmacy viagra
cheapest 4 quantity of viagra
cheap deal deal pill viagra
buy cheap viagra uk
order viagra on line
cheap deal pill pill viagra
buy depakote
cheapest generic silagra viagra
buy lasix
cheap site viagra
cheapest cialis
cialis no prescription
cheap kamagra viagra
cheap free price viagra
buy viagra online order
buy claritin
cheapest prices for viagra online
turning stone casino
buy internet viagra
cheapest viagra prices
buy cheap purchase uk viagra
cheap discount levitra online
cialis 20
buy discount price sale viagra viagra
cheap generic 50 mg viagra
buy viagra online pharmacy
order viagra without a prescription
buy online viagra
buy online drug viagra pharmacy
buy viagra in united kingdom
pontoon boat
viagra and cialas
cheap viagra uk
buy line viagra
buy cialis online viagra
viagra buy online
cheap viagra online
buy discount viagra viagra viagra
cheapest viagra online plus zenegra