I've made a program which is getting data from database and then authorizing, but the problem is only the last record is correct - logging in is succesful.
public class Test {
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost:3306/uzytkownicy";
static final String USER = "root";
static final String PASS = "";
public static void main(String[] args) throws SQLException, ClassNotFoundException {
System.out.print("login: ");
Scanner zm1= new Scanner(System.in);
String name = zm1.next();
System.out.print("pass: ");
Scanner zm2 = new Scanner(System.in);
String password = zm2.next();
try{
Class.forName("com.mysql.jdbc.Driver");
System.out.println("Connecting...");
Connection conn = DriverManager.getConnection(DB_URL,USER,PASS);
Statement stmt = conn.createStatement();
String sql = "SELECT logins, passwords FROM users";
ResultSet rs = stmt.executeQuery(sql);
String databasePassword = null;
String databaseUsername = null;
while (rs.next()) {
databaseUsername = rs.getString("logins");
databasePassword = rs.getString("passwords");
}
if (name.equals(databaseUsername) && password.equals(databasePassword)) {
System.out.println("Logged in!");
}
else {
System.out.println("Bad Pass/Login");
}
rs.close();
stmt.close();
conn.close();
}
catch(SQLException se){
se.printStackTrace();
}
}
}
If I'm understanding what you're trying to do (which I may not be), your problem is that the comparison of username and password is outside the while loop, so your:
while (rs.next())
just loops through the entire result set, so when the while loop ends, databaseUsername and databasePassword will be set to the values from the last row read.
Instead, move the comparison inside the loop and set a flag (defaulting to false) and break out of the loop if the correct username and password is found, then use that flag to determine what to print.
Also, you might want to read up on parameterized queries. You can actually have the database do all the work for you by using a PreparedStatement and making your query:
SELECT 1 from users where logins = ? and passwords = ?;
If the result set contains anything, then the user entered a valid username and password, otherwise they didn't. The question marks in the query would be set to name and password using the set* methods of PreparedStatement.
Another note--storing plaintext passwords is a horrible idea. If the table storing the passwords is exposed (through various attacks or just a disgruntled employee stealing it), then everyone has all your users' passwords. Eek! You might argue that you'll take steps to prevent that, but from a security perspective, it's best to assume someday the table will be compromised, and do everything you can to ensure that it's not too harmful.
Related
This is probably a easy question for you guys but I'm trying to access a variable set by an SQL statement to then be passed into another SQL statement in another class.
The idea is that when the user logs in, I get their StaffID then I want to use that number in another SELECT statement.
I've tried to make the variable public and access it from the other class but it returns empty.
LOGIN CODE:
public static String StaffID;
// SignIn ActionListener
signIn.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try{
Class.forName(DRIVER);
// Connection to the Database
con = DriverManager.getConnection(DATABASE_URL,"root","");
// Gets text from textfields and assigns them to variables
s1 = tfUsername.getText();
s2 = tfPassword.getText();
Statement st = con.createStatement();
// SQL Statements
st.executeQuery("SELECT * FROM login WHERE UName= '"+s1+"' and PWord = '"+s2+"'");
// Extracts data from statement to a result set
ResultSet rs = st.getResultSet();
if (rs.next())
{
// Gets text from Textfields and assigns them to variables
StaffID = rs.getString("StaffID");
}
OTHER CLASS:
try{
Class.forName(DRIVER);
// Connection to the Database
con = DriverManager.getConnection(DATABASE_URL,"root","");
signIn sign = new signIn();
//Creates Statement Connection
Statement st = con.createStatement();
// SQL Statements
st.executeQuery("SELECT * FROM rota WHERE StaffID = '"+sign.StaffID+"'");
// Extracts data from statement to a result set
ResultSet rs = st.getResultSet();
if (rs.next()) {
tfRotaTask1.setText(rs.getString("Task1"));
tfRotaTask2.setText(rs.getString("Task2"));
tfRotaTask3.setText(rs.getString("Task3"));
tfRotaTask4.setText(rs.getString("Task4"));
tfRotaTask5.setText(rs.getString("Task5"));
tfRotaTask6.setText(rs.getString("Task6"));
tfRotaTask7.setText(rs.getString("Task7"));
tfRotaTask8.setText(rs.getString("Task8"));
}
else{
//JOptionPane.showMessageDialog(null, "Staff Member Not Found");
}
To put this into context, I'm making a staff managment rota system.
Sorry if my Java seems poor :(
Any help will do.
Ok first thing first, wrap your Queries in One Class for more easy use.
public class QueryUtils
{
public static String staffId(...yourArgs)
{
String staffId = "";
// Make the logic for getting the StringId
return staffId;
}
}
Ok so you can call this query from anywhere in your application. Even from other queries. Use basic OOP and Patter Desings and you will solve this issues.
you don't inti the value of the StaffID until the condition of rs.next() is be true
try to make else statement like this
if (rs.next())
{
// Gets text from Textfields and assigns them to variables
StaffID = rs.getString("StaffID");
}
and then test the value of the StaffID in the other class if it null then you have somthing wrong in the executeQuery
because i don't see any thing wrong in your code
i've been trying to make this piece of code work work for a while now but seems like it wont. My User inputs Username and Password and then the program compares it to the DB. However it displays Invalid Credentials even though when i output the password it displays the exact same i've input.Just a few points, i know some of you are going to point on things like Using a seperate class for Connection, Check against username for password instead of using Select *, use hashings and all. But right now at the moment i just need to get this code work. Only after that i will be able to work on other aspects to ENHANCE its efficiency. Thank you all in advance.:)
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
// TODO add your handling code here:
Username1 = "jTextField1.getText()";
Password1 = "jPassword1Field2.geText()";
try
{
Class.forName("com.mysql.jdbc.Driver").newInstance();
String url = "jdbc:mysql://localhost:3306/";
String dbName = "VideoSystem" ;
String userName = "root";
String passWord = "**mypassword**";
Connection conn = DriverManager.getConnection(url+dbName, userName, passWord);
Statement st = conn.createStatement();
String sql = ("SELECT * FROM Identification");
ResultSet rs = st.executeQuery(sql);
while(rs.next())
{
password = rs.getString("Password");
if( Password1.equals(password))
{
MenuSelection obj1 = new MenuSelection();
obj1.setVisible(true);
}
else
{
JOptionPane.showMessageDialog(null, "Invalid Credentials", "System Message", JOptionPane.INFORMATION_MESSAGE);
}
}
conn.close();
}
catch (Exception e)
{
System.err.println("Got an exception! ");
System.err.println(e.getMessage());
}
}
Those two lines:
Username1 = "jTextField1.getText()";
Password1 = "jPassword1Field2.geText()";
They are string literals, so unless your password is literally jPassword1Field2.geText(), there's not gonna be a match. I think you meant:
Username1 = jTextField1.getText();
Password1 = jPassword1Field2.getText();
Note however, that JPasswordField.getText() is deprecated since Java 2. You should use getPassword() instead:
Password1 = new String(jPassword1Field2.getPassword());
The documentation justifies the deprecation of getText() with "security reasons" that I can't claim to understand, but you still shouldn't use deprecated parts of the API.
And I know you some of the below already and none of that is part of your question, but I really suggest that you
Check against the username. It should be obvious why.
Hash passwords. Always.
Only fetch what you need, mostly for performance reasons. Usually the best way is to use a WHERE clause in SQL (that brings the need to sanitize your input, but you should do that anyway) and building a list of columns instead of fetching *.
Use backticks for database/table/column names in SQL to avoid things like accidentally using a keyword as table/column name or so.
Applying the above, I suggest the following query (assuming the name field is called Username):
PreparedStatement st = conn.prepareStatement("SELECT `Password` FROM `Identification` WHERE `Username` = ?");
st.setString(1, Username1);
ResultSet rs = st.executeQuery();
public int addUsers(int USER_ID,String FIRST_NAME,String LAST_NAME,String PASSWORD,String USERNAME,String USER_PERMISSION) throws SQLException {
Connection conn = null;
conn = getConnectivity(conn) ;
getConnectivity(conn);
String sqlSelect = "SELECT * from USER_DETAILS";
PreparedStatement pres = conn.prepareStatement(sqlSelect);
ResultSet rs1 = pres.executeQuery();
if(rs1.next()){
String Username = rs1.getString(5);
System.out.println("username found "+Username);
System.out.println("username input " + USERNAME);
System.out.println("password input " + PASSWORD);
if (Username.equals(USERNAME)){
System.out.println("Username already exists");
conn.close();
}
else{
System.out.println("FOUND ELSE");
String sql = "INSERT INTO USER_DETAILS VALUES (?,?,?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, USER_ID);
ps.setString(2, FIRST_NAME);
ps.setString(3,LAST_NAME);
ps.setString(4,PASSWORD);
ps.setString(5,USERNAME);
ps.setString(6,USER_PERMISSION);
int result = ps.executeUpdate();
System.out.println(result);
}
}
conn.close();
return USER_ID;
}
and for login I am using
public boolean login(String USERNAME, String PASSWORD) throws SQLException
{
boolean result = false;
Connection conn = null;
conn = getConnectivity(conn) ;
String sqlSelect = "SELECT * from USER_DETAILS";
PreparedStatement pres = conn.prepareStatement(sqlSelect);
ResultSet rs1 = pres.executeQuery();
if(rs1.next()){
String Username = rs1.getString(5);
String Password = rs1.getString(4);
String UserPermission = rs1.getString(6);
System.out.println("username found "+Username);
System.out.println("username input " + USERNAME);
System.out.println("password input " + PASSWORD);
if (Username.equalsIgnoreCase(USERNAME) && Password.equalsIgnoreCase(PASSWORD) && UserPermission.equalsIgnoreCase("blocked")){
System.out.println("User Logged in");
conn.close();
}
System.out.println("gets out of the code");
}
conn.close();
return result;
}
first of all it is allowing to enter more than one entry, so duplicates occurring regardless of my if statement, and when i add fresh new data and try to see I can log in, it still compares with previously added data and does not work. Can someone see what am i doing wrong here. please thanks
below is the system print out i get ,
Connection Valid
username found kamran (don't know why he is still picking up this column)
username input macbook (these i have already in my database)
password input hello (these i have already in my database)
gets out of the code
Connection Valid
Connection Valid
username found kamran (don't know why he is still picking up this column)
username input macho (these i have already in my database)
password input hello (these i have already in my database)
FOUND ELSE (dont know why it adds data when they already exist in database)
1
Your code doesn't make sense: you are querying for all users and only checking the first returned user if it matches. Of course that is going to fail if the first returned user doesn't match: in addUsers you will try to add the user if the first user returned doesn't match, in login a user can only login if it is the first user.
You need to use a WHERE clause to only request the user you want to check:
// Note: this assumes a case insensitive collation
String sqlSelect = "SELECT * from USER_DETAILS WHERE username = ?";
try (PreparedStatement pres = conn.prepareStatement(sqlSelect)) {
pres.setString(1, USERNAME);
try (ResultSet rs1 = pres.executeQuery()) {
if (!rs1.next) {
// user doesn't exist yet, create...
}
}
}
You need to do something similar for login (but then with if (rs1.next()) instead).
There are more problems with your current code: you are storing plaintext passwords: you should really hash them with a strong password hash like PBKDF2. Also please follow the java naming conventions. Variables and parameters are camelcase so not USERNAME but username (or userName), not UserPermission, but userPermission. This improves the readability for people who are used to the java naming conventions.
How do I validate a certain email and password while an user logs in?
protected void doPost(HttpServletRequest request, HttpServletResponse res) throws IOException, ServletException {
String email=request.getParameter("email");
String pass=request.getParameter("pass");
OutputStream out = res.getOutputStream();
try{
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:8080/college", "root", "root");
Statement st=con.createStatement();
String strSQL = "SELECT email,password FROM student";
How do I continue after the SELECT statement? I would prefer using the if...else statement to do the validation.
First close all connection resources properly - use a Java 7 try-with-resources.
Here is an simple example:
final String email = request.getParameter("email");
final String pass = request.getParameter("pass");
try (final Connection con = DriverManager.getConnection("jdbc:mysql://localhost:8080/student", "root", "root");
final PreparedStatement statement = con.prepareStatement("SELECT COUNT(*) AS count FROM student WHERE email=? AND password=?");) {
statement.setString(1, email);
statement.setString(2, pass);
try (final ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
final int rows = resultSet.getInt("count");
if (rows > 1) {
throw new IllegalStateException("More than one row returned!");
}
boolean validUser = rows == 1;
}
}
}
But really you should hash passwords in the database. Use something like jBcrypt. Your code would then look like:
final String email = request.getParameter("email");
final String pass = request.getParameter("pass");
try (final Connection con = DriverManager.getConnection("jdbc:mysql://localhost:8080/student", "root", "root");
final PreparedStatement statement = con.prepareStatement("SELECT pass FROM student WHERE email=?");) {
statement.setString(1, email);
statement.setString(2, pass);
try (final ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
final String hash = resultSet.getString("pass");
final boolean valid = BCrypt.checkpw(pass, hash);
}
}
}
Obviously you need to add error checking if there are no rows returned from the query. You also need to check that only one row is returned. But I leave that as an exercise.
you can use if, if you like. Use the input as your where statement and then check to see if there is a match, error or null, then execute whatever you want it to do.
You can use email and password in the SQL statement itself. like:
SELECT email, password from student where email = ? and password = ?
prepare above statement and bind the parameters.
This way validation will be done on the DB and you just need to check the result count (which has to be 1). You should have index on email column to have better SQL performance.
Do you relay need to fetch all students?
PreparedStatement st = con.prepareStatement("SELECT count(*) FROM student WHERE email=? AND password=?");
st.setString(1, email);
st.setString(2, pass);
ResultSet rs = st.executeQuery();
rs.next();
int count = rs.getInt(1);
if (count == 1) {
// password and email are correct
}
For this answer, I'll assume that by "validate email and password", what you mean is you want to authenticate the user based on their email address and a password. And not that you want to check whether the email address is a real email address.
So, the first thing you need to do is encrypt the passwords in your database, using a hash algorithm and a random salt. You record the salt alongside the hashed password.
Next thing is, when the user logs in, you look up the salt for that user, and you perform the same hash with the salt. Then you compare the result of that with the previously saved password hash, and if they're the same, then the passwords were the same.
It's important that the salt be random and different for every user.
Plenty of reading to be found on the above terms on the Internets.
Once you've done that, you should also apply the very sensible suggestions in other answers to only select the user you want, and handle your resources correctly.
WARNING I am not an expert on security, and neither are you. If you're implementing a log-in system for an exercise, fine. If it's for the real world, use something that's been written by someone who knows what they're doing.
I have a web application using Java/JSP that was running off a MySQL database which I've now moved to Sybase.
I've changed what I believe are all the relevant connection parts (Sybase Connector and relevant code)
I've been using PreparedStatements for my queries. What was working in MySQL is now no longer returning anything (errors or results).
The first simple query I've been testing is a login form which should be matching the user values for name and password in the table "appuser".
The Prepared Statement in the code provided used to work but no longer does with Sybase.
Relevant code is below. Let me know if anything else is needed.
public void connectDB() throws ClassNotFoundException, SQLException, InstantiationException, IllegalAccessException
{
/* String userName="****";
String password="******";
String url="jdbc:sybase:sybdev1dw/ETL_MON";
Class.forName("com.sybase.jdbc4.jdbc.SybDriver").newInstance();
conn=DriverManager.getConnection(url, userName, password); */
String driver = "com.sybase.jdbc2.jdbc.SybDriver";
String host = "********";
String dbName = "********";
String url = "jdbc:sybase:Tds:" + host + ":4110" +"?SERVICENAME=" + dbName;
String username = "*******";
String password = "*********";
Class.forName(driver);
conn = DriverManager.getConnection(url, username, password);
System.out.println("Connection successful"+conn);
}
public Boolean loginAction(String name, String pass, String role,HttpServletRequest request) throws SQLException {
Boolean valid=false;
session=request.getSession();
PreparedStatement stmt=conn.prepareStatement("SELECT pass FROM appuser WHERE name=?");
stmt.setString(1, name);
results=stmt.executeQuery();
System.out.println("loginAction:"+results.getFetchSize());
while(results.next())
{
if(results.getString("pass").equals(pass))
{
valid=true;
session.setAttribute("name",name);
session.setAttribute("role",role);
}
else
{
valid=false;
}
}
System.out.println("loginAction:"+valid);
return valid;
}
String compare is failing possibly because of spaces being padded to the database column.
result.getString("pass").trim().equals(pass.trim())
One other suggestion. Instead of doing a while(results.next()) , do an if(results.next()) if you are confident it will always return exactly one row ( or zero ).