通过将类链接到btnRegister将数据插入数据库

时间:2014-01-03 04:44:32

标签: vb.net

我是编程新手,并尝试通过youtube教程学习VB.net。

我创建了一个Windows窗体应用,供用户创建新帐户。

为了安全起见,我还尝试应用hash和salt技术来存储密码。

我遇到的主要问题是维护一个名为“DatabaseManager”和“DataHandling”的两个类,“btnRegister”中的代码和名为“Test”的数据库之间的成功连接。

程序运行正常。当我在填写“txtUsername.Text”和“txtPassword.Text”后单击btnRegister时,它会显示错误"Column User_ID does not allow nulls."

所以这就是我不断遇到问题的地方。我试图让它工作很多,我不知道它为什么不记录新数据。这是我的代码。我使用V Studio 2012.请帮忙。     为了清楚起见,我复制了一些来自互联网的代码并试图让它们与班级一起工作

Imports System
Imports System.IO
Imports System.Text
Imports System.Data.OleDb
Imports System.Data
Imports System.Windows.Forms
Imports System.Data.SqlClient
Imports System.Security.Cryptography

Public Class DatabaseManager

    Private Const CONNECTION_STRING As String = "Data Source=(localdb)\Projects;Initial Catalog=Test;Integrated Security=True"

    Private connection As SqlConnection = Nothing
    Private usersdataadapter As SqlDataAdapter = Nothing

    Sub New()
        connection = New SqlConnection(CONNECTION_STRING)
        usersdataadapter = New SqlDataAdapter("select * from Test", connection)
    End Sub

    Public Sub Register(ByVal Username As String, ByVal Password As String)

        connection.Open()

        Dim usersDataset As New DataSet()
        usersdataadapter.FillSchema(usersDataset, SchemaType.Source, "Test")
        Dim table As DataTable = usersDataset.Tables("Test")

        Dim newRecord As DataRow = table.NewRow()
        newRecord("Username") = Username
        newRecord("Password") = Password
        table.Rows.Add(newRecord)

        Dim command As New SqlCommandBuilder(usersdataadapter)
        usersdataadapter.Update(usersDataset, "Test")
        usersDataset.Dispose()

        connection.Close()
    End Sub
        Public Function UsernameAvailable(ByVal username As String) As Boolean

        Dim usersDataset As New DataSet()
        usersdataadapter.FillSchema(usersDataset, SchemaType.Source, "Test")
        usersdataadapter.Fill(usersDataset, "Test")

        Dim table As DataTable = usersDataset.Tables("Test")
        For i As Integer = 0 To table.Rows.Count - 1
            Dim currnetUser As String = table.Rows(i)("Username").ToString().Trim()
            If (currnetUser = username) Then
                usersDataset.Dispose()
                connection.Close()
                Return False
            End If
        Next
        Return True
        usersDataset.Dispose()
        connection.Close()
    End Function
    Public Function Login(ByVal username As String, ByVal password As String) As Boolean

        Dim usersDataset As New DataSet()
        usersdataadapter.FillSchema(usersDataset, SchemaType.Source, "Test")
        usersdataadapter.Fill(usersDataset, "Test")

        Dim table As DataTable = usersDataset.Tables("Test")
        For i As Integer = 0 To table.Rows.Count - 1
            Dim currnetUser As String = table.Rows(i)("Username").ToString().Trim()
            Dim currnetPassword As String = table.Rows(i)("Password").ToString().Trim()

            If (currnetUser = username AndAlso currnetPassword = password) Then
                usersDataset.Dispose()
                connection.Close()
                Return True
            End If
        Next
        usersDataset.Dispose()
        connection.Close()
        Return False
    End Function
End Class

Imports System
Imports System.Text
Imports System.Data.OleDb
Imports System.Data
Imports System.Data.SqlClient
Imports System.Windows.Forms
Imports System.Security.Cryptography

Public Class DataHandling

    Inherits Form1
    Public Shared Function GenerateRandomString() As String
        Dim i_key As Integer
        Dim Random1 As Single
        Dim arrIndex As Int16
        Dim sb As New StringBuilder
        Dim RandomLetter As String

        Dim KeyLetters As String = "abcdefghijklmnopqrstuvwxyz"
        Dim KeyNumbers As String = "0123456789"
        Dim KeyLength As Integer = 12

        Dim LettersArray = KeyLetters.ToCharArray
        Dim NumbersArray = KeyNumbers.ToCharArray

        For i_key = 1 To KeyLength
            Randomize()
            Random1 = Rnd()
            arrIndex = -1

            If (CType(Random1 * 111, Integer)) Mod 2 = 0 Then

                Do While arrIndex < 0
                    arrIndex = _
                     Convert.ToInt16(LettersArray.GetUpperBound(0) _
                     * Random1)
                Loop
                RandomLetter = LettersArray(arrIndex)

                If (CType(arrIndex * Random1 * 99, Integer)) Mod 2 <> 0 Then
                    RandomLetter = LettersArray(arrIndex).ToString
                    RandomLetter = RandomLetter.ToUpper
                End If
                sb.Append(RandomLetter)
            Else
                Do While arrIndex < 0
                    arrIndex = _
                      Convert.ToInt16(NumbersArray.GetUpperBound(0) _
                      * Random1)
                Loop
                sb.Append(NumbersArray(arrIndex))
            End If
        Next

        Return sb.ToString
    End Function

    Public Shared Function CheckPassword(ByVal plainText As String, ByVal passwordHash As Byte(), ByVal salt As Byte()) As Boolean
        Dim encoding As New System.Text.UTF8Encoding

        'Retrieve Salt String from byte array
        Dim saltStr As String = encoding.GetString(salt)
        Dim hashable As String = Trim(plainText) & Trim(saltStr)

        ' Convert into hash strings
        Dim testhash As String = EncryptStringAsHash(hashable)
        Dim realHash As String = encoding.GetString(passwordHash)

        ' Compare and return result
        Return testhash = realHash
    End Function

    Public Shared Function EncryptStringAsHash(ByVal value As String) As String
        Dim encoding As New System.Text.UTF8Encoding
        Dim stringBytes As Byte() = encoding.GetBytes(value)

        Dim SHhash As SHA512Managed = New SHA512Managed
        Dim hash As String = Convert.ToBase64String(SHhash.ComputeHash(stringBytes))

        Return hash
    End Function

    Public Shared Function ConvertStringToByteArray(ByVal value As String) As Byte()
        Dim encoding As New System.Text.UTF8Encoding
        Return encoding.GetBytes(value)
    End Function
End Class

Imports System.IO
Imports System.Text
Imports System.Security.Cryptography
Imports System.Data.OleDb
Imports System.Windows.Forms
Imports System.Data.OleDb.OleDbConnection
Imports System.Data.SqlClient

Public Class Form1

    Dim maxrows As Integer
    Dim incdec As Integer
    Dim con As New OleDb.OleDbConnection
    Dim dbprovider As String
    Dim dbsource As String
    Dim ds As New DataSet
    Dim da As OleDb.OleDbDataAdapter
    Dim sql As String

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim con As New OleDbConnection
        Dim dbprovider As String
        Dim dbsource As String
        dbprovider = "PROVIDER = Microsoft.ACE.OLEDB.12.0;"
        dbsource = "Data Source=(localdb)\Projects;Initial Catalog=Test;Integrated Security=True"
        con.ConnectionString = dbprovider & dbsource

    End Sub

    Private Sub btnRegister_Click(sender As Object, e As EventArgs) Handles btnRegister.Click

        Dim dbmanager As New DatabaseManager
        Dim Data As New DataHandling

        'Generate Hash and Salt for password
        Dim salt As String = DataHandling.GenerateRandomString
        Dim hashable As String = Trim(txtPassword.Text) & Trim(salt) 'txtPassword.Text used to be password
        Dim hash As String = DataHandling.EncryptStringAsHash(hashable)

    Dim confirmationId As String = System.Guid.NewGuid.ToString
        Dim reg As user

        reg.Username = txtUsername.Text     'txtUsername.Text used to be username
        reg.Password = DataHandling.ConvertStringToByteArray(hash)
        reg.Salt = DataHandling.ConvertStringToByteArray(salt)

        If dbmanager.UsernameAvailable(txtUsername.Text) Then

            dbmanager.Register(txtUsername.Text, txtPassword.Text)

    Dim password As String
            If txtPassword.Text = String.Empty Then
                password = "217tABCDEF42#$tolq"
            Else
                password = txtPassword.Text
            End If

            Dim salt As String = GenerateRandomString(12)
            Dim hashable As String = Trim(password) & Trim(salt)
            MsgBox("Hashable = " & hashable)
            Dim hash As String = EncryptStringAsHash(hashable)
            CheckPassword(password, ConvertStringToByteArray(hash), ConvertStringToByteArray(salt))

            frmAccessGranted.Show()
            Me.Hide()
        Else
            MessageBox.Show("Cannot Register, Username Already Taken!")
        End If
    End Sub

    Private Sub btnClear_Click(sender As Object, e As EventArgs) Handles btnClear.Click
        txtUsername.Clear()
        txtPassword.Clear()
    End Sub

End Class

2 个答案:

答案 0 :(得分:0)

我认为您的User表User_id值只是缺少Identity Specification选项。它使User_id字段自动生成,并为您添加到

中的每个用户增加1(默认情况下)

如果您有SQL Server管理工作室,则可以将此选项放在:

右键点击User table -> Select "Desing" -> Select "User_id" field -> in "Column Propetries"窗口,将“Indentity Specification”选项设为“Yes”并保存

示例SQL创建表的命令可能是这样的:

CREATE TABLE User (User_id BIGINT IDENTITY NOT NULL, Username NVARCHAR(100) NOT NULL, Password NVARCHAR(100) NOT NULL)

答案 1 :(得分:0)

代码中的问题不在VB端,而是在数据库中。

您已将主键设置为UserId,但您没有将任何值传递给userId,您只是将值传递给用户名和密码。

所以有两种方法可以解决这个问题

  1. 您也可以从VB代码发送用户ID
  2. 您可以通过以下代码将UserId列作为自动增量字段

    CREATE TABLE [dbo]。[Test1](    [id] [int] IDENTITY(1,1)NOT NULL,     YourColumnname1数据类型,     YourColumnname2数据类型

  3. 这仅适用于sqlserver 2008的更高版本

    alter table tablename 
    alter column columnname 
    add Identity(100,1)
    

    了解更多 Click here