[ad_1]
Desarrollé una aplicación con base de datos de servidor SQL. Tengo una tabla para el inicio de sesión de usuario con administrador y usuario normal. El problema cuando inicio sesión con un usuario normal abre el formulario tanto para el administrador como para el usuario normal. En resumen, abre dos formularios cuando inicio sesión con un usuario normal. Por favor asiste.
Lo que he probado:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Data.SqlClient; namespace Stokvel_Management_System { public partial class Login : Form { public Login() { InitializeComponent(); } public string constring = "Data Source=LAPTOP-TINYIKOB\\SQLEXPRESS;Initial Catalog=Stokvel;Integrated Security=True"; private void BtnLogin_Click(object sender, EventArgs e) { SqlConnection con = new SqlConnection(constring); con.Open(); SqlDataAdapter da = new SqlDataAdapter("select count(*) from loginTab where UserName='" + txtUsername.Text + "' and Password='" + txtPassword.Text + "'and Type='" + UsercomboBox.Text + "'", con); DataTable dt = new DataTable(); da.Fill(dt); if (dt.Rows[0][0].ToString() == "1") { SqlDataAdapter da1 = new SqlDataAdapter("select Type from loginTab where UserName='" + txtUsername.Text + "' and Password='" + txtPassword.Text + "'", con); DataTable dt1 = new DataTable(); da1.Fill(dt1); if (dt1.Rows[0][0].ToString() == "Admin") con.Close(); { Hide(); Admin ad = new Admin(); ad.Show(); } if(dt1.Rows[0][0].ToString()=="User") { Hide(); User us = new User(); us.Show(); } } } } }
Solución 2
Esto me parece excesivamente complejo. Todo lo que realmente necesita es leer la fila que coincide con el nombre de usuario y la contraseña proporcionados y devuelve el tipo de usuario. Con esa información, puede abrir el formulario de administrador o de usuario. Crear dos adaptadores de datos y tablas de datos solo para leer una sola fila es un desperdicio de recursos. Algo como:
string queryString = "select Type from loginTab where UserName='" + txtUsername.Text + "' and Password='" + txtPassword.Text + "'"; string usertype = "None"; using (SqlConnection connection = new SqlConnection( connectionString)) { SqlCommand command = new SqlCommand( queryString, connection); connection.Open(); using(SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { usertype = reader[0]; // returned value } } } if (usertype == "Admin") { Hide(); Admin ad = new Admin(); ad.Show(); } else if(usertype == "User") { Hide(); User us = new User(); us.Show(); } else { // invalid type, or no matching record. }
Solución 1
Primero tienes que lidiar con los peores problemas, así que te explicaré lo último que has notado.
1) Nunca concatene cadenas para crear un comando SQL. Lo deja completamente expuesto a ataques de inyección SQL accidentales o deliberados que pueden destruir toda su base de datos. Utilice siempre consultas parametrizadas en su lugar.
Cuando concatenas cadenas, causas problemas porque SQL recibe comandos como:
SELECT * FROM MyTable WHERE StreetAddress = 'Baker's Wood'
La cita que agregó el usuario termina la cadena en lo que respecta a SQL y surgen problemas. Pero podría ser peor. Si en su lugar escribo esto: “x’;DROP TABLE MyTable;–” Entonces SQL recibe un comando muy diferente:
SELECT * FROM MyTable WHERE StreetAddress = 'x';DROP TABLE MyTable;--'
Que SQL ve como tres comandos separados:
SELECT * FROM MyTable WHERE StreetAddress = 'x';
Un SELECT perfectamente válido
DROP TABLE MyTable;
Un comando perfectamente válido para “eliminar la tabla”
--'
Y todo lo demás es un comentario.
Así lo hace: selecciona las filas coincidentes, elimina la tabla de la base de datos e ignora todo lo demás.
¡Así que SIEMPRE utilice consultas parametrizadas! O prepárese para restaurar su base de datos desde la copia de seguridad con frecuencia. Realizas copias de seguridad con regularidad, ¿no?
¿Y en una PANTALLA DE INICIO DE SESIÓN? ¡Eso es positivamente suicida ya que ni siquiera tengo que ser un usuario para destruir tu base de datos!
2) Nunca almacene contraseñas en texto claro: es un riesgo de seguridad importante. Hay información sobre cómo hacerlo aquí: Almacenamiento de contraseñas: cómo hacerlo.[^]
Y recuerde: si tiene usuarios de la Unión Europea, entonces se aplica el RGPD y eso significa que debe manejar las contraseñas como datos confidenciales y almacenarlas de manera segura. El texto no es ninguna de esas cosas y las multas pueden ser… um… pendientes. En diciembre de 2018, una empresa alemana recibió una multa relativamente baja de 20.000 euros precisamente por eso.
3) No verifica si la base de datos devolvió alguna fila: si escribe mal, generará un error de “índice fuera de rango” y su aplicación fallará.
4) Solo cierras la conexión para administradores. En lugar de cerrar manualmente la conexión, rodee todo el código DB en using
bloques y el sistema los ordenará automáticamente.
5) El problema que has notado… Mira tu código:
if (dt1.Rows[0][0].ToString() == "Admin") con.Close(); { Hide(); Admin ad = new Admin(); ad.Show(); }
Si la condición coincide, cierra la conexión. Luego, siempre ejecuta el código entre llaves incluso si la condición no coincide…
[ad_2]
コメント