The system is pretty simple. Here is how the database looks:
table users:
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| userid | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(45) | NO | UNI | NULL | |
| password | varchar(32) | NO | | NULL | |
| email | varchar(75) | NO | UNI | NULL | |
+----------+-------------+------+-----+---------+----------------+
table banbyip
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| ipAddr | varchar(45) | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
table banlist
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| ipAddr | varchar(45) | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
table loginattempts
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| ipaddr | varchar(45) | NO | | NULL | |
| username | varchar(45) | NO | | NULL | |
| count | int(11) | NO | | NULL | |
+----------+-------------+------+-----+---------+-------+
Here are the jsp, they are the pages shown to the user(View): Home:
index.jsp
<!DOCTYPE html>
<html>
<head>
<title>Login System</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Bootstrap -->
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<!-- End Bootstrap -->
</head>
<body>
<nav class="navbar navbar-default" >
<ul class="nav navbar-nav">
<li class="active"><a href="index.html"> Home</a></li>
<li><a href="login.jsp"> Login </a> </li>
<li><a href="register.jsp"> Register </a> </li>
</ul>
</nav>
</body>
</html>
Login: login.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login</title>
<!-- Bootstrap -->
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<!-- End Bootstrap -->
</head>
<body>
<nav class="navbar navbar-default" >
<ul class="nav navbar-nav">
<li><a href="index.html"> Home</a></li>
<li class="active"><a href="login.jsp"> Login </a> </li>
<li><a href="register.jsp"> Register </a> </li>
</ul>
</nav>
<form action="login" method="POST" role="form">
<c:if test="${sessionScope.failed == 1}">
<div class="form-group">
<h3>Login failed</h3>
</div>
</c:if>
<div class="form-group">
<label for="username">Username:</label>
<input type="text" class="form-control" id="username" name="username">
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" class="form-control" id="password" name="password">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</body>
</html>
Register:
register.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Register</title>
<!-- Bootstrap -->
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<!-- End Bootstrap -->
</head>
<body>
<nav class="navbar navbar-default" >
<ul class="nav navbar-nav">
<li><a href="index.html"> Home</a></li>
<li><a href="login.jsp"> Login </a> </li>
<li class="active"><a href="register.jsp"> Register </a> </li>
</ul>
</nav>
<form action="register" method="POST" role="form">
<div class="form-group">
<c:if test="${sessionScope.Invalid_username == 1}">
<h6> Invalid username </h6><br />
<c:set var="Invalid_username" value="0" scope="session" />
</c:if>
<c:if test="${sessionScope.unameAlreadyRegistered == 1}">
<h6> Username is already registered</h6><br />
<c:set var="unameAlreadyRegistered" value="0" scope="session" />
</c:if>
<label for="username">Username:</label>
<input type="text" class="form-control" id="username" name="username" placeholder="Username">
</div>
<div class="form-group">
<c:if test="${sessionScope.mailAlreadyRegistered == 1}">
<h6> E-mail is already registered</h6><br />
<c:set var="mailAlreadyRegistered" value="0" scope="session" />
</c:if>
<c:if test="${sessionScope.Invalid_email == 1}">
<h6> E-mail is invalid</h6><br />
<c:set var="Invalid_email" value="0" scope="session" />
</c:if>
<label for="email">Email address:</label>
<input type="email" class="form-control" id="email" name="email" placeholder="Email">
</div>
<div class="form-group">
<c:if test="${sessionScope.Invalid_password == 1}">
<h6> Password is invalid</h6><br />
<c:set var="Invalid_password" value="0" scope="session" />
</c:if>
<c:if test="${sessionScope.passwordsDontMatch == 1}">
<h6> Passwords don't match</h6><br />
<c:set var="passwordsDontMatch" value="0" scope="session" />
</c:if>
<label for="password">Password:</label>
<input type="password" class="form-control" id="password" name="password" placeholder="Password" >
</div>
<div class="form-group">
<label for="passwordRepeat">Repeat password:</label>
<input type="password" class="form-control" id="passwordRepeat" name="passwordRepeat" placeholder="Repeat password">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</body>
</html>
banned.jsp
<!DOCTYPE html>
<%@ page contentType="text/html;charset=windows-1251"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251"/>
<title>banned</title>
</head>
<body>
You are banned
</body>
</html>
And here are the Java classes, which are helping the servlets to do their job.
DataBase.java
package loginsystem;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DataBase {
private final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
private final String DB_URL = "jdbc:mysql://localhost/loginsystem";
private final String username = "root";
private final String password = "123456";
private Connection connection;
private PreparedStatement statement;
public DataBase() {
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection(DB_URL, username, password);
} catch (ClassNotFoundException e) {
System.out.println("An exception occured: " + e.toString());
} catch (SQLException e) {
System.out.println("An exception occured: " + e.toString());
}
}
public Object[] createParams(Object... args) {
Object params[] = new Object[args.length];
for (int i = 0; i < args.length; i++) {
params[i] = args[i];
}
return params;
}
public ResultSet runSQL(String sql, Object[] params, boolean isUpdate) {
if (!validateSQL(sql, params)) {
return null;
}
try {
statement = connection.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
int j = i + 1;
statement.setObject(j, params[i]);
}
if (isUpdate) {
statement.executeUpdate();
return null;
} else {
return statement.executeQuery();
}
} catch (SQLException e) {
System.out.println(e.toString());
return null;
}
}
public int getUserId(String username) {
String sql = "SELECT user_id FROM users WHERE username = ?;";
int id;
try {
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1, username);
ResultSet rs = ps.executeQuery();
rs.next();
id = rs.getInt("user_id");
} catch (SQLException e) {
System.out.print(e.toString());
id = -1;
}
return id;
}
private boolean validateSQL(String sql, Object[] params) {
int objectsCount = params.length;
int questionMarks = 0;
for (int i = 0; i < sql.length(); i++) {
if (sql.charAt(i) == '?') {
questionMarks++;
}
}
return objectsCount == questionMarks;
}
}
Logger.java
package loginsystem;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Logger {
private final String checkIfRecordExists = "SELECT ipaddr FROM loginattempts WHERE ipaddr = ?;";
private final String clearRecord = "UPDATE loginattempts SET count = 0 WHERE ipaddr = ?;";
private final String incrementRecord = "UPDATE loginattempts SET count = count + 1 WHERE ipaddr = ?";
private final String addRecord = "INSERT INTO loginattempts(ipaddr, username, count) VALUES(?, ?, 0)";
private final String getCountByUserName = "SELECT count FROM loginattempts WHERE username = ?";
private final String getCountByIp = "SELECT count FROM loginattempts WHERE ipaddr = ?";
private final String getCount = "SELECT count FROM loginattempts WHERE ipaddr = ? AND username = ?";
private final DataBase db = new DataBase();
public Logger() {
}
public boolean checkIfRecordExists(String IP) {
boolean retVal = false;
ResultSet rs;
try {
rs = db.runSQL(checkIfRecordExists, db.createParams(IP), false);
retVal = rs.isBeforeFirst();
} catch (SQLException e) {
System.out.println(e.toString());
}
return retVal;
}
public void clearRecord(String IP) {
if (!checkIfRecordExists(IP)) {
return;
}
db.runSQL(clearRecord, db.createParams(IP), true);
}
public void incrementRecord(String IP, String username) {
if (!checkIfRecordExists(IP)) {
addRecord(IP, username);
} else {
db.runSQL(incrementRecord, db.createParams(IP), true);
}
}
public int getCountByUserName(String username) {
int count = 0;
try {
ResultSet rs = db.runSQL(getCountByUserName, db.createParams(username), false);
while (rs.next()) {
count += rs.getInt("count");
}
} catch (SQLException e) {
System.out.println(e.toString());
}
return count;
}
public int getCountByIp(String IP) {
int count = 0;
try {
ResultSet rs = db.runSQL(getCountByIp, db.createParams(IP), false);
rs.beforeFirst();
while (rs.next()) {
count += rs.getInt("count");
}
rs.close();
} catch (SQLException e) {
System.out.println(e.toString());
}
return count;
}
public int getCount(String IP, String username) {
int count = 0;
try {
ResultSet rs = db.runSQL(getCount, db.createParams(IP, username), false);
rs.beforeFirst();
while (rs.next()) {
count += rs.getInt("count");
}
rs.close();
} catch (SQLException e) {
System.out.println(e.toString());
}
return count;
}
private void addRecord(String IP, String username) {
db.runSQL(addRecord, db.createParams(IP, username), true);
}
}
HashingMethod.java
package loginsystem;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class HashingMethod
{
private MessageDigest md5;
public HashingMethod(){
try{
md5 = MessageDigest.getInstance("MD5");
}
catch(NoSuchAlgorithmException e){
System.out.println(e.toString());
}
}
public String hashPassword(String password){
md5.update(password.getBytes());
byte[] digest = md5.digest();
StringBuffer strBuff = new StringBuffer();
for (byte b : digest) {
strBuff.append(String.format("%02x", b & 0xff));
}
return strBuff.toString();
}
}
BAN.java
package loginsystem;
import java.sql.ResultSet;
import java.sql.SQLException;
public class BAN {
private String addBanUser = "INSERT INTO banlist VALUES(?)";
private String removeBanUser = "DELETE FROM banlist WHERE userId = ?";
private String isBannedUser = "SELECT * FROM banlist WHERE userId = ?";
private String addBanIP = "INSERT INTO banbyip VALUES(?)";
private String removeBanIP = "DELETE FROM banbyip WHERE ipAddr = ?";
private String isBannedIP = "SELECT * FROM banbyip WHERE iAddr = ?";
private DataBase db = new DataBase();
public BAN(){
}
public void addBan(String param, boolean isIP){
if(isIP)
db.runSQL(addBanIP, db.createParams(db.getUserId(param)), false);
else
db.runSQL(addBanUser, db.createParams(db.getUserId(param)), false);
}
public void removeBan(String param, boolean isIP){
if(isIP)
db.runSQL(removeBanIP, db.createParams(db.getUserId(param)), false);
else
db.runSQL(removeBanUser, db.createParams(db.getUserId(param)), false);
}
public boolean isBanned(String param, boolean isIP){
try{
ResultSet rs;
if(isIP)
rs = db.runSQL(isBannedIP, db.createParams(db.getUserId(param)), true);
else
rs = db.runSQL(isBannedUser, db.createParams(db.getUserId(param)), true);
return rs.isBeforeFirst();
}catch(SQLException e){
System.out.println(e.toString());
return false;
}
}
}
And finally here are the servlets:
Login.java
package loginsystem;
import java.io.IOError;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletConfig;
@WebServlet(name = "Login", urlPatterns = { "/login" })
public class Login extends HttpServlet {
private final int MAX_LEN_USERNAME = 30;
private final int MAX_LEN_PASSWORD = 32;
private final String validateLogin = "SELECT password FROM users WHERE username = ?";
private Logger logger;
private BAN ban;
private DataBase db;
private HashingMethod hasher;
private static final String CONTENT_TYPE = "text/html; charset=windows-1251";
public void init(ServletConfig config) throws ServletException {
super.init(config);
db = new DataBase();
ban = new BAN();
logger = new Logger();
hasher = new HashingMethod();
}
private void failedAttempt(HttpServletRequest request, HttpServletResponse response) throws IOException{
String username = request.getParameter("username");
String IP = request.getRemoteAddr();
logger.incrementRecord(IP,username);
request.getSession().setAttribute("failed", 1);
if(logger.getCountByUserName(username) > 10)
ban.addBan(username, false);
if(logger.getCountByIp(IP) > 10)
ban.addBan(IP,true);
response.sendRedirect("login.jsp");
}
private boolean validateData(String username, String password){
if(username.equals("") || password.equals(""))
return false;
if(username.length() > MAX_LEN_USERNAME || password.length() > MAX_LEN_PASSWORD)
return false;
return true;
}
private boolean validateLogin(String username, String password){
ResultSet rs;
String passwordFromDb = "";
try{
rs = db.runSQL(validateLogin, db.createParams(username), false);
rs.next();
passwordFromDb = rs.getString("password");
}catch(SQLException e){
System.out.println(e.toString());
}
return passwordFromDb.equals(hasher.hashPassword(password));
}
private void succesullAttempt(HttpServletRequest request, HttpServletResponse response) throws IOException{
response.sendRedirect("http://9gag.com");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
if(validateData(username, password)){
if(ban.isBanned(username, false) || ban.isBanned(request.getRemoteAddr(), true))
response.sendRedirect("banned.jsp");
if(validateLogin(username, password)){
succesullAttempt(request, response);
}
else{
failedAttempt(request, response);
}
}
else
failedAttempt(request, response);
}
}
Register.java
package loginsystem;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
@WebServlet(name = "Register", urlPatterns = { "register" })
public class Register extends HttpServlet {
private static final String CONTENT_TYPE = "text/html; charset=windows-1251";
private final String checkIfUserExists = "SELECT username FROM users WHERE username = ?";
private final String checkIfEmailExists = "SELECT username FROM users WHERE email = ?";
private final String inserUser = "INSERT INTO users(username, password, email) VALUES(?, ? ,?)";
private DataBase db = new DataBase();
private HashingMethod hasher = new HashingMethod();
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
private boolean validateEmail(String email) {
String EMAIL_PATTERN =
"^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
Pattern pattern;
pattern = Pattern.compile(EMAIL_PATTERN);
Matcher matcher;
matcher = pattern.matcher(email);
return !matcher.matches();
}
private boolean checkIfUserExists(String username) {
ResultSet rs;
rs = db.runSQL(checkIfUserExists, db.createParams(username), false);
try {
return rs.isBeforeFirst();
} catch (SQLException e) {
System.out.println(e.toString());
return true;
}
}
private boolean checkIfEmailExists(String email) {
ResultSet rs = db.runSQL(checkIfEmailExists, db.createParams(email), false);
try {
return rs.isBeforeFirst();
} catch (SQLException e) {
System.out.println(e.toString());
return true;
}
}
private boolean validateInput(String username, String password, String repeatPassword, String email,
HttpSession session) {
// username
if (username.equals("") || username.length() > 42) {
session.setAttribute("Invalid_username", 1);
return false;
}
if (checkIfUserExists(username)) {
session.setAttribute("unameAlreadyRegistered", 1);
return false;
}
// password
if (password.equals("")) {
session.setAttribute("Invalid_password", 1);
return false;
}
if (!password.equals(repeatPassword)) {
session.setAttribute("passwordsDontMatch", 1);
return false;
}
// email
if (email.equals("") || validateEmail(email)) {
session.setAttribute("Invalid_email", 1);
return false;
}
if (checkIfEmailExists(email)) {
session.setAttribute("mailAlreadyRegistered", 1);
return false;
}
//else
return true;
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = (request.getParameter("username") != null) ? request.getParameter("username") : "";
String password = (request.getParameter("password") != null) ? request.getParameter("password") : "";
String passwordRepeat =
(request.getParameter("passwordRepeat") != null) ? request.getParameter("passwordRepeat") : "";
String email = (request.getParameter("email") != null) ? request.getParameter("email") : "";
if (validateInput(username, password, passwordRepeat, email, request.getSession())) {
String hashedPassword = hasher.hashPassword(password);
db.runSQL(inserUser, db.createParams(username, hashedPassword, email), true);
response.sendRedirect("login.jsp");
} else {
response.sendRedirect("register.jsp");
}
}
}
The system is far from well written, hopefully with your help I can make it better.