ASP.NET - Login e acesso a dados com inclusão, exclusão e alteração


Neste artigo você vai aprender a criar uma aplicação ASP.NET no VS.NET que faz acesso a dados e implementa a leitura , exclusão e alteração de dados usando ADO.NET.

O acesso a aplicação é validado por um formulário de Login onde  o usuário deverá informar o nome e a senha do  usuário para ter acesso as funcionalidades descritas.

Você vai aprender como evitar a injeção SQL (Sql injection) na prática e vai aprender também como criar um controle web do usuário (web user control) para usar no projeto.

Crie um novo projeto do tipo ASP.NET Web Application com o nome de ASPNETDBAdmin. A estrutura da aplicação é a seguinte :

Solução - ASPNETDBAdmin

projeto - ASPNETDBAdmin

  • frmconteudo.aspx - formulário : permite incluir e alterar dados
  • header.ascx - controle web do usuário : contém o cabeçalho das páginas
  • index.aspx - contém  o menu de opções da aplicação.
  • listaconteudo.aspx - exibe os dados em um DataList e permite editar e excluir dados.
  • login.aspx - página de login : acessa a tabela admin onde estão o nome e senha do usuário
  • web.config - contém a string de acesso ao banco de dados  dados.mdb
  • Styles.css - arquivo com estilos usados pelas páginas da aplicação.

O esquema simplificado da aplicação é o seguinte:

Para iniciar vamos criar um arquivo Web.Config onde iremos definir a string de conexão com o banco de dados e a segurança baseada em formulários. Abaixo temos o código para estes dois recursos:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <appSettings>
    <add key="ConnectionString"
      value="Provider=Microsoft.JET.OLEDB.4.0; Data Source=D:\ASPNETDBAdminControl\database\dados.mdb" />
  </appSettings>
  ...................

  ....................

    .................

  <authentication mode="Forms"> 
         <forms loginUrl="login.aspx" name="DBLogin" />
    </authentication>		

   .......................

</Configuration>

Para saber mais sobre como implementar a segurança baseada em formulários  leia o artigo :
ASP.NET - Usando segurança baseada em formulários

Para saber mais sobre como tratar arquivos de configuração leia o artigo  : NET - Tratando arquivos de configuração.

A primeira página a ser exibida quando do primeiro acesso é a página login.aspx:

Nesta página temos os seguintes controles:

 1- O UserControl - header.ascx

 2-  Duas caixas de texto , 3 Labels e um botão de comando (Login)

O código da página Login.aspx é exibido a seguir:

Public Class login
        Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        lblMsg.Text = "Informe o usuário e senha para efetuar o login."
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim cn As New OleDb.OleDbConnection
        Dim cm As New OleDb.OleDbCommand
        Dim dr As OleDb.OleDbDataReader
        Dim usuario As String = txtUsername.Text
        Dim senha As String = txtPassword.Text

        'SQL Injection ==>> se voce digitar 'or' 1 '=' 1 no usuario e na senha vai passar
        Try
            cn.ConnectionString = ConfigurationSettings.AppSettings("ConnectionString")
            cn.Open()
            cm.Connection = cn
            cm.CommandText = "Select * From admin where usuario='" & usuario & "' and senha='" & senha & "'"
            dr = cm.ExecuteReader()
            If dr.HasRows Then
                System.Web.Security.FormsAuthentication.RedirectFromLoginPage(usuario, False)
            Else
                lblMsg.Text = "Usuário ou Senha Incorreta!"
            End If
        Catch ex As Exception
            lblMsg.Text = ex.Message
        End Try
    End Sub
End Class

Este código recebe o nome do usuário e a senha ,  abre uma conexão e seleciona os dados da tabela admin para o critério informado. Se não houver dados então o acesso é negado.

Perceba que a instrução SQL é montada da maneira clássica e isto não é nada bom , pois permite que através da injeção SQL qualquer um tenha acesso a seu site. Para isto basta digitar 'or' 1 '=' 1 no campo usuário e repetir  no campo senha. (Faça você mesmo o teste).

Este tipo de vulnerabilidade é comum em páginas ASP/ASP.NET que usam código SQL para validar dados.

Se você quer escapar desta armadilha use consultas parametrizadas. Assim no código acima ao invés de usar a instrução SQL :

 "Select * From admin where usuario='" & usuario & "' and senha='" & senha & "'"

use  a seguinte consulta SQL parametrizada:

"Select * From admin where ((usuario=@usuario)  and (senha=@senha))"

Os parâmetros deverão ser informados conforme abaixo:

With cmd.Parameters
    .Add(New OleDbParameter("@usuario",usuario))
    .Add(New OleDbParameter("@senha",senha))
End With

Para saber mais sobre a Injeção SQL , leia o artigo : Previna-se contra a injeção SQL

Outro detalhe importante é que a senha , neste meu exemplo esta como texto totalmente aberta , ela deveria estar , no mínimo criptografada, para garantir uma segurança melhor. (Na verdade além disto eu deveria estar usando SSL).

O arquivo header.ascx é um controle do usuário que você pode criar da seguinte forma:

Após o usuário ser validado a aplicação exibe a página index.aspx

Nesta página temos :
  • O user control - header.ascx .
  • O controle Hyperlink com o texto -  Incluir Novo Conteúdo - remete para a página frmconteudo.aspx
  • O controle Hyperlink com o texto -  Listar Conteúdo - remete para a página listaconteudo.aspx
  • O controle LinkButton - Logout

O LinkButton é igual a Button mas é exibido como um link. Um link normal apenas faz referência a uma página, indicando que o browser deve requisitar a página sem efetuar envio de dados , remetendo apenas os parâmetros GET.

No controle Hyperlink temos o elemento <a href>. Ele apenas renderiza um link simples sem Posts de formulários ou round-trips.

A pagina frmconteudo.aspx permite a inclusão e alteração de dados e  tem o seguinte layout:

  Neste formulário temos os controles:
  • Label - titulo e nome das caixas de texto
  • TextBox - caixas de texto para titulo e conteúdo
  • Button - os botões Salvar e Cancelar
  • Hyperlink - o link Voltar

O código deste formulário é dado abaixo:

ublic Class NovoConteudo
    Inherits System.Web.UI.Page
    Dim totalReg As Long
    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        If Request.QueryString("id") <> "" And Not IsPostBack() Then
            'define as variáveis objetos para a conexão , comando e datareader
            Dim cn As New OleDb.OleDbConnection
            Dim cm As New OleDb.OleDbCommand
            Dim dr As OleDb.OleDbDataReader

            'abre a conexão e seleciona os dados
            Try
                cn.ConnectionString = ConfigurationSettings.AppSettings("ConnectionString")
                cn.Open()
                cm.Connection = cn
                'seleciona o registro com o id informado
                cm.CommandText = "Select * From Conteudo Where id=" & Request.QueryString("id")
                dr = cm.ExecuteReader()

                dr.Read()
                'le os valores do datareader e os exibe nas caixas de texto
                txtTitulo.Text = dr.GetValue(1)   'titulo
                txtConteudo.Text = dr.GetValue(2)  'conteudo
            Catch ex As Exception
                lblMsg.Text = ex.Message
            End Try

        End If
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Response.Redirect("index.aspx")
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        'define as variaveis objeto para conexao , comando 
        Dim cn As New OleDb.OleDbConnection
        Dim cm As New OleDb.OleDbCommand
        Dim titulo As String = txtTitulo.Text
        Dim conteudo As String = txtConteudo.Text

        'abre a conexao e atualiza ou insere um registro na base de dados
        Try
            cn.ConnectionString = ConfigurationSettings.AppSettings("ConnectionString")
            cn.Open()
            cm.Connection = cn
            If Request.QueryString("id") <> "" Then
                cm.CommandText = "Update Conteudo Set Titulo='" & titulo & "', conteudo='" & conteudo & "' " _
                                    & "Where id=" & Request.QueryString("id")
                lblMsg.Text = "O registro do Conteúdo foi atualizado com sucesso."
                cm.ExecuteNonQuery()
            Else
                'verifica o total de registros na tabela
                verificaID()
                'nao permite incluir mais que 12 registros na tabela
                If totalReg < 12 Then
                    If txtTitulo.Text <> "" And txtConteudo.Text <> "" Then
                        cm.CommandText = "Insert Into Conteudo (titulo,conteudo)" _
                                            & " Values('" & titulo & "','" & conteudo & "')"
                        cm.ExecuteNonQuery()
                        lblMsg.Text = "O registro do Conteúdo foi incluido com sucesso."
                        txtTitulo.Text = ""
                        txtConteudo.Text = ""
                    Else
                        lblMsg.Text = "Informe valores para o titulo e o conteúdo..."
                    End If
                Else
                    lblMsg.Text = "O limite para incluir registros já foi alcançado. Delete alguns registros..."
                End If
            End If
        Catch ex As Exception
            lblMsg.Text = ex.Message
        End Try
    End Sub
    Private Sub verificaID()
        'define um objeto para conexao
        Dim cn1 As New OleDb.OleDbConnection
        Dim dr1 As OleDb.OleDbDataReader
        'abre a conexão e seleciona os dados
        Try
            cn1.ConnectionString = ConfigurationSettings.AppSettings("ConnectionString")
            cn1.Open()
            ' le o numero de registros na tabela
            Dim cm1 As New OleDb.OleDbCommand("SELECT COUNT(*) FROM Conteudo", cn1)
            'obtem o total
            totalReg = CLng(cm1.ExecuteScalar())
        Catch ex As Exception
            lblMsg.Text = ex.Message
        Finally
            cn1.Close()
        End Try
    End Sub
End Class

 

Este código inclui dados usando a instrução SQL - INSERT / INTO e atualiza dados usando a instrução UPDATE / SET. Para contar os registros da tabela conteudo estou usando a instrução SQL - SELECT COUNT(*) FROM Conteudo.

Para saber mais sobre operações básicas usando SQL leia o artigo - ASP.NET - Operações básicas com Banco de dados.

Eu criei a rotina VerificaID() que faz a conexão com a tabela e conta quantos registros ela tem guardando o valor na variável totalReg. Faço isto para não permitir a inclusão de mais de 12 registros na tabela. (adivinha onde eu faço esta restrição ???)

Finalmente temos o código da página listaconteudo.aspx que exibe os dados da tabela e permite editar e excluir um registro.

Neste formulário temos :
  • Duas Labels - para mensagens
  • Um DataList - para exibir os dados
  • Um Hyperlink - Voltar

Para saber mais sobre o componente DataList leia o artigo : ASP.NET - Usando o componente DataList.

O código do formulário é o seguinte :

Public Class listaconteudo
    Inherits System.Web.UI.Page

   Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        'define as variavies objeto para conexão , comando e datareader
        Dim cn As New OleDb.OleDbConnection
        Dim cm As New OleDb.OleDbCommand
        Dim dr As OleDb.OleDbDataReader
        'abre a conexão e executa o comando sobre a tabela do banco de dados
        Try
            cn.ConnectionString = ConfigurationSettings.AppSettings("ConnectionString")
            cn.Open()
            cm.Connection = cn
            If Request.QueryString("delid") <> "" Then
                cm.CommandText = "DELETE From Conteudo Where ID=" & Request.QueryString("delid")
                cm.ExecuteNonQuery()
                lblMsg.Text = "Conteúdo excluído: " & Request.QueryString("delid")
            End If
            cm.CommandText = "Select id as ID,titulo as Titulo,left(conteudo,50) as Conteudo From Conteudo"
            dr = cm.ExecuteReader()
            DataList1.DataSource = dr
            DataList1.DataBind()
        Catch ex As Exception
            lblMsg.Text = ex.Message
        End Try
    End Sub

    Private Sub DataList1_ItemCommand(ByVal source As Object, ByVal e As _ 
                                  System.Web.UI.WebControls.DataListCommandEventArgs) Handles DataList1.ItemCommand
        Select Case e.CommandName
            Case "Edita"
                Response.Redirect("frmconteudo.aspx?id=" & e.CommandArgument)
            Case "Deleta"
                'lblMsg.Text = "Deleta: " & e.CommandArgument
                Response.Redirect("listaconteudo.aspx?delid=" & e.CommandArgument)
        End Select
    End Sub

End Class

Este código apenas exibe os dados no DataList e implementa a edição e a exclusão. 

Pegue o projeto completo aqui : DBAdmin.zip

Até mais ver ...


José Carlos Macoratti