Added some logging and moved cookie stuff to the manager

This commit is contained in:
Ziver Koc 2018-08-04 18:42:46 +02:00
parent 8e56ff406a
commit a4eb5c613d
9 changed files with 255 additions and 244 deletions

View file

@ -7,7 +7,7 @@
<Environment type="java.lang.String" name="ADMIN_EMAIL" value="admin@example.com" />
<Environment type="java.lang.String" name="ADMIN_EMAIL_NICE" value="Example.com Admin" />
<Environment type="java.lang.String" name="SMTP_HOST" value="127.0.0.1" />
<Environment type="java.lang.String" name="DATA_PATH" value="PATH TO DATA FOLDER" />
<Environment type="java.lang.String" name="DATA_PATH" value="C:\\Users\\Ziver\\Desktop\\Downloads\\zallery" />
<Resource
name="jdbc/mysql"
@ -16,7 +16,7 @@
username="zallery"
password="password"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://db:3306/zallery"
url="jdbc:mysql://localhost:3306/zallery"
maxActive="8"
maxIdle="4"
validationQuery="SELECT 1"

View file

@ -56,6 +56,9 @@
</library>
</orderEntry>
<orderEntry type="library" name="Maven: se.koc:zutil:1.0.2-219" level="project" />
<orderEntry type="library" name="Maven: javax.mail:javax.mail-api:1.6.1" level="project" />
<orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
<orderEntry type="library" name="Maven: se.koc:zutil:1.0.2-219" level="project" />
<orderEntry type="library" name="Maven: commons-fileupload:commons-fileupload:1.2.1" level="project" />
<orderEntry type="library" name="Maven: commons-io:commons-io:2.5" level="project" />
<orderEntry type="library" name="Maven: dom4j:dom4j:1.6.1" level="project" />

View file

@ -61,8 +61,6 @@ CREATE TABLE `User` (
`email` varchar(50) DEFAULT NULL,
`emailVerified` tinyint(1) NOT NULL,
`password` varchar(32) DEFAULT NULL,
`facebookUid` varchar(12) DEFAULT NULL,
`sessionId` varchar(32) DEFAULT NULL,
`ipHost` varchar(20) DEFAULT NULL,
`loginDate` datetime DEFAULT NULL,
`sessionHash` varchar(32) DEFAULT NULL,

View file

@ -44,7 +44,7 @@ public class Zallery extends HttpServlet{
try {
Context context = new InitialContext();
// Check if Zallery has been properly configured
if ("PATH TO DATA FOLDER".equals(context.lookup("java:comp/env/DATA_PATH")))
if (((String) context.lookup("java:comp/env/DATA_PATH")).isEmpty())
throw new ServletException("Zallery has not been properly configured, set proper configuration in Zallery.xml context file.");
WEBSITE_NAME = (String)context.lookup("java:comp/env/WEBSITE_NAME");
@ -72,7 +72,7 @@ public class Zallery extends HttpServlet{
try {
return new DBConnection("jdbc/mysql");
} catch (Exception e) {
throw new ServletException(e);
throw new ServletException("Was unable to initialize DB connection", e);
}
}

View file

@ -20,7 +20,7 @@ import zutil.log.LogUtil;
import zall.Zallery;
@DBTable("Folder")
public class Folder extends DBBean{
public class Folder extends DBBean {
private static final Logger logger = LogUtil.getLogger();
private transient String name;
@ -32,11 +32,11 @@ public class Folder extends DBBean{
private boolean isPrivate;
public static Folder load(DBConnection db, Long id) throws SQLException{
public static Folder load(DBConnection db, Long id) throws SQLException {
return load(db, Folder.class, id);
}
public static List<Folder> loadSubFolders(DBConnection db, Folder folder, User requestingUser) throws SQLException{
public static List<Folder> loadSubFolders(DBConnection db, Folder folder, User requestingUser) throws SQLException {
PreparedStatement sql = db.getPreparedStatement("SELECT * FROM Folder WHERE parent=? AND (isPrivate=0 OR user=? OR ?)");
sql.setLong(1, folder.getId());
sql.setLong(2, folder.user);
@ -44,7 +44,7 @@ public class Folder extends DBBean{
return DBConnection.exec(sql, DBBeanSQLResultHandler.createList(Folder.class, db));
}
public static Folder loadRoot(DBConnection db, User user) throws SQLException{
public static Folder loadRoot(DBConnection db, User user) throws SQLException {
PreparedStatement sql = db.getPreparedStatement("SELECT * FROM Folder WHERE path=? AND (isPrivate=0 OR user=? OR ?)");
sql.setString(1, "/");
sql.setLong(2, user.getId());
@ -52,35 +52,36 @@ public class Folder extends DBBean{
return DBConnection.exec(sql, DBBeanSQLResultHandler.create(Folder.class, db));
}
public static Folder load(DBConnection db, String path, User user) throws SQLException{
public static Folder load(DBConnection db, String path, User user) throws SQLException {
PreparedStatement sql = db.getPreparedStatement("SELECT * FROM Folder WHERE path=? AND user=?");
sql.setString(1, path);
sql.setLong(2, user.getId());
return DBConnection.exec(sql, DBBeanSQLResultHandler.create(Folder.class, db));
}
public static List<Folder> load(DBConnection db, User user) throws SQLException{
if( user.getId() == null )
public static List<Folder> load(DBConnection db, User user) throws SQLException {
if (user.getId() == null)
return Collections.emptyList();
PreparedStatement sql = db.getPreparedStatement("SELECT * FROM Folder WHERE user=?");
sql.setLong(1, user.getId() );
sql.setLong(1, user.getId());
return DBConnection.exec(sql, DBBeanSQLResultHandler.createList(Folder.class, db));
}
public Folder(){
date = new Timestamp( System.currentTimeMillis() );
public Folder() {
date = new Timestamp(System.currentTimeMillis());
}
public String getName(){
if(name == null){
public String getName() {
if (name == null) {
String[] tmp = path.split("/");
name = tmp[tmp.length-1];
name = tmp[tmp.length - 1];
}
String userName = getUser() != null ? getUser().getName() : "UNKNOWN";
String tmp = name.replaceAll("\\{NAME\\}", userName);
return tmp;
}
public User getUser(){
public User getUser() {
if (userInstance == null) {
try {
DBConnection db = Zallery.getDB();
@ -92,94 +93,100 @@ public class Folder extends DBBean{
}
return userInstance;
}
public void setUser(User user){
public void setUser(User user) {
this.user = user.getId();
this.userInstance = null;
}
public boolean isPrivate(){
public boolean isPrivate() {
return isPrivate;
}
public void setPrivate(boolean priv){
public void setPrivate(boolean priv) {
this.isPrivate = priv;
}
public String getPath(){
public String getPath() {
String tmp = path.replaceAll("\\{NAME\\}", getUser().getName());
return tmp;
}
public void setName(String name){
public void setName(String name) {
this.name = name;
if( parent.path.endsWith("/") )
this.path = parent.path+name;
if (parent.path.endsWith("/"))
this.path = parent.path + name;
else
this.path = parent.path+"/"+name;
this.path = parent.path + "/" + name;
}
public void setParent(Folder parent){
if( this.parent != parent ){
public void setParent(Folder parent) {
if (this.parent != parent) {
this.parent = parent;
//parent.addSubFolder( this );
if( parent.path.endsWith("/") )
this.path = parent.path+name;
if (parent.path.endsWith("/"))
this.path = parent.path + name;
else
this.path = parent.path+"/"+name;
this.path = parent.path + "/" + name;
}
}
public Folder getParent(){
public Folder getParent() {
return parent;
}
public Timestamp getDate(){
public Timestamp getDate() {
return date;
}
/**
* @param filename is the name of the file
* @param size specifies the size of the image
* @return a File object that points to the physical file on the disk,
* or null if the user or the filename is null
* @param filename is the name of the file
* @param size specifies the size of the image
*/
public File getFile(String filename, Image.Size size){
public File getFile(String filename, Image.Size size) {
// Zallery not initialized.
while( Zallery.DATA_PATH.isEmpty() ){
logger.warning("Zallery not initialized or DATA_PATH not set!");
return null;
if (Zallery.DATA_PATH.isEmpty()) {
throw new NullPointerException("Zallery not initialized yet or DATA_PATH not set!");
}
if( user < 0 || filename == null )
if (user < 0 || filename == null)
return null;
StringBuilder tmp = new StringBuilder();
// Get the Root path of the given size
tmp.append( Zallery.DATA_PATH );
if( tmp.charAt(tmp.length()-1) != File.separatorChar )
tmp.append( File.separatorChar );
tmp.append( size.toString() );
if( path.charAt(0) != '/' )
tmp.append( File.separatorChar );
tmp.append(Zallery.DATA_PATH);
if (tmp.charAt(tmp.length() - 1) != File.separatorChar)
tmp.append(File.separatorChar);
tmp.append(size.toString());
if (path.charAt(0) != '/')
tmp.append(File.separatorChar);
// Add UserID and this folders path
String tmp_path = path.replaceAll("\\{NAME\\}", ""+user);
String tmp_path = path.replaceAll("\\{NAME\\}", "" + user);
tmp_path = tmp_path.replaceAll("/", Matcher.quoteReplacement(File.separator));
tmp.append( tmp_path );
tmp.append(tmp_path);
// check if folder exists or else create it
File folder = new File(tmp.toString());
if( !folder.exists() )
if( !folder.mkdirs() ){
logger.warning("Unable to create new folders: '"+folder+"'");
throw new RuntimeException("Unable to create new folders: '"+folder+"'");
if (!folder.exists())
if (!folder.mkdirs()) {
logger.warning("Unable to create new folders: '" + folder + "'");
throw new RuntimeException("Unable to create new folders: '" + folder + "'");
}
// Add the filename
if( tmp.charAt(tmp.length()-1) != File.separatorChar )
tmp.append( File.separatorChar );
if (tmp.charAt(tmp.length() - 1) != File.separatorChar)
tmp.append(File.separatorChar);
tmp.append(filename);
logger.finest( "File path: "+tmp.toString() );
logger.finest("File path: " + tmp.toString());
return new File(tmp.toString());
}
public static Folder genRoot(){
public static Folder genRoot() {
Folder root = new Folder();
root.parent = null;
root.path = "/";

View file

@ -5,10 +5,6 @@ import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.List;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import zutil.Hasher;
import zutil.db.DBConnection;
import zutil.db.bean.DBBean;
@ -16,8 +12,8 @@ import zutil.db.bean.DBBeanSQLResultHandler;
import zutil.db.bean.DBBean.*;
@DBTable("User")
public class User extends DBBean{
public enum AuthType{
public class User extends DBBean {
public enum AuthType {
USER_INPUT, COOKIE
}
@ -29,19 +25,18 @@ public class User extends DBBean{
protected Timestamp loginDate;
// security
protected transient AuthType authBy;
protected String sessionId;
protected String ipHost;
protected String sessionHash;
protected String cookieHash;
protected boolean superUser;
protected boolean enabled;
public static User load(DBConnection db, Long id) throws SQLException{
public static User load(DBConnection db, Long id) throws SQLException {
return load(db, User.class, id);
}
public static List<User> load(DBConnection db) throws SQLException{
public static List<User> load(DBConnection db) throws SQLException {
PreparedStatement sql = db.getPreparedStatement("SELECT * FROM User");
return DBConnection.exec(sql, DBBeanSQLResultHandler.createList(User.class, db));
}
@ -52,7 +47,7 @@ public class User extends DBBean{
*
* @return the user object or null if non where found
*/
public static User load(DBConnection db, String email) throws SQLException{
public static User load(DBConnection db, String email) throws SQLException {
PreparedStatement sql = db.getPreparedStatement(
"SELECT * FROM User WHERE email=? LIMIT 1");
sql.setString(1, email);
@ -73,71 +68,53 @@ public class User extends DBBean{
*
* @return the user object or null if non where found
*/
public static User loadBySessionHash(DBConnection db, String hash) throws SQLException{
public static User loadByCookieHash(DBConnection db, String hash) throws SQLException {
PreparedStatement sql = db.getPreparedStatement(
"SELECT * FROM User WHERE sessionHash=? LIMIT 1");
"SELECT * FROM User WHERE cookieHash=? LIMIT 1");
sql.setString(1, hash);
return DBConnection.exec(sql, DBBeanSQLResultHandler.create(User.class, db));
}
public User(){
public User() {
// Default values
emailVerified = false;
superUser = false;
enabled = false;
}
/**
* Registers the User to the Host machine that sent the request,
* this method alters the bean, so a call to save() is recommended
*
* @param db is the DB connection
* @param request is the request from the Host/Client
* @throws SQLException
*/
public void registerOnHost(HttpServletRequest request, HttpServletResponse response, DBConnection db, boolean cookie) throws SQLException{
loginDate = new Timestamp( System.currentTimeMillis() );
sessionId = request.getSession().getId();
ipHost = request.getRemoteAddr();
sessionHash = generateSessionHash();
if( cookie ){
Cookie c = new Cookie("sessionHash", sessionHash );
c.setMaxAge(5*24*60*60); // 5 days
response.addCookie( c );
}
}
public boolean verifyEmail(String hash) {
return emailVerified = generateEmailVerificationHash().equals(hash);
}
public String generateEmailVerificationHash(){
return Hasher.MD5( "##helloWorld-->2011"+email+name+password );
public String generateEmailVerificationHash() {
return Hasher.MD5("##helloWorld-->2011" + email + name + password);
}
public Timestamp getLoginDate() {
if( loginDate == null )
if (loginDate == null)
loginDate = new Timestamp(0);
return loginDate;
}
public void setLoginDate(Timestamp loginDate) {
this.loginDate = loginDate;
}
public void setAuthBy(AuthType authBy){
public void setAuthBy(AuthType authBy) {
this.authBy = authBy;
}
public AuthType getAuthBy(){
public AuthType getAuthBy() {
return authBy;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ -145,65 +122,64 @@ public class User extends DBBean{
public String getEmail() {
return email;
}
public void setEmail(String email) {
if( this.email != null && this.email.equals(email) )
if (this.email != null && this.email.equals(email))
return;
emailVerified = false;
this.email = email;
}
public boolean isEmailVerified(){
public boolean isEmailVerified() {
return emailVerified;
}
public void setEmailVerified(boolean verified){
public void setEmailVerified(boolean verified) {
this.emailVerified = verified;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = Hasher.MD5( password );
this.password = Hasher.MD5(password);
}
public String getSessionId() {
return sessionId;
public String getCookieHash() {
return cookieHash;
}
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
public String getSessionHash() {
return sessionHash;
}
public void setSessionHash(String sessionHash) {
this.sessionHash = sessionHash;
}
public String generateSessionHash(){
return Hasher.MD5( ""+sessionId+ipHost+loginDate+password );
public void setCookieHash(String cookieHash) {
this.cookieHash = cookieHash;
}
public String getIpHost() {
return ipHost;
}
public void setIpHost(String ipHost) {
this.ipHost = ipHost;
}
public boolean isSuperUser(){
public boolean isSuperUser() {
return superUser;
}
public void setSuperUser(boolean superUser){
public void setSuperUser(boolean superUser) {
this.superUser = superUser;
}
public boolean isEnabled(){
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled){
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean equals(User u){
return u != null && getId() == u.getId();
public boolean equals(User u) {
return u != null && getId().equals(u.getId());
}
}

View file

@ -4,17 +4,20 @@ import zall.bean.User;
import zall.manager.AuthenticationManager;
import zall.page.LoginServlet;
import zall.page.RegisterServlet;
import zutil.log.LogUtil;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.logging.Logger;
/**
* This filter will check if user is isValid if not will redirect to /login page
*/
@WebFilter(urlPatterns = "/")
public class AuthenticationFilter implements Filter {
private static final Logger logger = LogUtil.getLogger();
@Override
public void init(FilterConfig filterConfig) { }
@ -28,9 +31,11 @@ public class AuthenticationFilter implements Filter {
if (requestURI.equals(LoginServlet.URI) ||
requestURI.equals(RegisterServlet.URI) ||
AuthenticationManager.isValid(user, (HttpServletRequest) request)) {
logger.finest("User already authenticated, continuing filter chain.");
chain.doFilter(request, response);
} else {
// do not continue the filter pipeline forward to login page
logger.fine("User not authenticated, redirecting to login page.");
request.getRequestDispatcher(LoginServlet.URI).forward(request, response);
}
}

View file

@ -8,8 +8,7 @@ import zutil.Hasher;
import zutil.db.DBConnection;
import zutil.log.LogUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.*;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.logging.Logger;
@ -23,21 +22,27 @@ public class AuthenticationManager {
public static final String SESSION_KEY_USER = "zall_user";
public static final String SESSION_KEY_AUTH_HASH = "zall_ueser_session_hash";
public static final long SESSION_TIMEOUT = 1000*60*60*24*3; // 3day
public static final long SESSION_TIMEOUT = 3*24*60*60*1000; // 2 day
public static final String COOKIE_KEY_USER_HASH = "zall_auth";
public static final int COOKIE_TIMEOUT = 10*24*60*60; // 10 days
/**
* Authenticate a username and password and return the associated Uaer object
*/
public static User authenticate(DBConnection db, String email, String password) throws SQLException {
public static User authenticate(DBConnection db, String email, String password, HttpServletRequest request, HttpServletResponse response) throws SQLException {
User user = User.load(db, email);
// Valid email?
if( user != null ){
if (user.getPassword().equals(Hasher.MD5(password))) {
userAuthenticated(db, user, User.AuthType.USER_INPUT);
setUserAuthenticated(db, user, User.AuthType.USER_INPUT, request, response);
return user;
} else {
logger.info("Incorrect password for username: " + user);
}
} else {
logger.info("Incorrect username provided: " + user);
}
return null;
}
@ -47,24 +52,41 @@ public class AuthenticationManager {
*
* @return a user object or null authentications fails
*/
public static User authenticate(DBConnection db, HttpServletRequest request) throws SQLException{
String sessionHash = ServletUtil.getCookieValue(request.getCookies(), SESSION_KEY_AUTH_HASH);
User user = User.loadBySessionHash(db, sessionHash);
public static User authenticate(DBConnection db, HttpServletRequest request, HttpServletResponse response) throws SQLException{
String cookieHash = ServletUtil.getCookieValue(request.getCookies(), SESSION_KEY_AUTH_HASH);
if (cookieHash != null) {
User user = User.loadByCookieHash(db, cookieHash);
if( user != null &&
user.getIpHost().equals(request.getRemoteAddr()) &&
user.getLoginDate().getTime() + SESSION_TIMEOUT > System.currentTimeMillis()){
userAuthenticated(db, user, User.AuthType.COOKIE);
if (user != null) {
if (request.getRemoteAddr().equals(user.getIpHost()) &&
user.getLoginDate().getTime() + SESSION_TIMEOUT > System.currentTimeMillis()) {
setUserAuthenticated(db, user, User.AuthType.COOKIE, request, response);
return user;
} else {
logger.info("Cookie hash has expired or have incorrect ipHost: " + cookieHash);
}
} else {
logger.info("Cookie hash not associated with any user: " + cookieHash);
}
}
return null;
}
private static void userAuthenticated(DBConnection db, User user, User.AuthType authType) throws SQLException {
private static void setUserAuthenticated(DBConnection db, User user, User.AuthType authType, HttpServletRequest request, HttpServletResponse response) throws SQLException {
user.setLoginDate(new Timestamp(System.currentTimeMillis()));
user.setAuthBy(authType);
user.setIpHost(request.getRemoteAddr());
user.setCookieHash(Double.toHexString(Math.random()));
user.save(db);
logger.info("User(" + user.getName() + ") authenticated by " + user.getAuthBy());
setUserSession(user, request.getSession());
if(authType != User.AuthType.COOKIE){
Cookie c = new Cookie(COOKIE_KEY_USER_HASH, user.getCookieHash());
c.setMaxAge(COOKIE_TIMEOUT);
response.addCookie(c);
}
logger.info("User(" + user.getEmail() + ") authenticated by " + user.getAuthBy());
}
/**
@ -88,7 +110,7 @@ public class AuthenticationManager {
return false;
if(!user.isEnabled())
return false;
if(user.getSessionHash() == null || user.getSessionHash().isEmpty() )
if(user.getCookieHash() == null || user.getCookieHash().isEmpty() )
return false;
switch(user.getAuthBy()){
@ -96,7 +118,7 @@ public class AuthenticationManager {
if (!user.isEmailVerified()) return false;
case COOKIE:
String sessionHash = ServletUtil.getCookieValue(request.getCookies(), SESSION_KEY_AUTH_HASH);
return user.getSessionHash().equals(sessionHash) &&
return user.getCookieHash().equals(sessionHash) &&
user.getIpHost().equals(request.getRemoteAddr());
}
return false;
@ -126,7 +148,7 @@ public class AuthenticationManager {
* Reset the user authentication. In plain word: logout user.
*/
public static void reset(DBConnection db, User user) throws SQLException {
user.setSessionHash(null);
user.setCookieHash(null);
user.save(db);
}

View file

@ -30,12 +30,13 @@ public class LoginServlet extends ZalleryServlet {
// Authenticate with cookies
if (user == null)
user = AuthenticationManager.authenticate(db, request);
user = AuthenticationManager.authenticate(db, request, response);
// Forward user
if (user != null) {
include(JSP_FILE, request, response);
} else {
logger.fine("User(" + user.getEmail() + ") already authenticated, forwarding to gallery.");
redirect(GalleryServlet.URI, request, response);
}
}
@ -45,14 +46,13 @@ public class LoginServlet extends ZalleryServlet {
UserMessage msgs = UserMessage.getUserMessage(request.getSession());
User user = AuthenticationManager.authenticate(db,
request.getParameter("email"),
request.getParameter("password"));
request.getParameter("password"),
request, response);
// Successful login
if (user != null) {
user.registerOnHost(request, response, db, true );
AuthenticationManager.setUserSession(user, request.getSession());
forward("/", request, response);
logger.fine("Authenticated user(" + user.getEmail() + ") successfully, forwarding to gallery.");
forward(GalleryServlet.URI, request, response);
}
// Failed login
else {