|
|
|
@ -1,102 +1,28 @@ |
|
|
|
package org.leolo.nrapi.web; |
|
|
|
package org.leolo.nrapi.web; |
|
|
|
|
|
|
|
|
|
|
|
import org.leolo.nrapi.Constants; |
|
|
|
|
|
|
|
import org.leolo.nrapi.manager.DatabaseManager; |
|
|
|
|
|
|
|
import org.leolo.nrapi.util.HttpReqRespUtils; |
|
|
|
|
|
|
|
import org.slf4j.Logger; |
|
|
|
|
|
|
|
import org.slf4j.LoggerFactory; |
|
|
|
|
|
|
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
|
|
|
|
|
|
|
import org.springframework.web.bind.annotation.RequestMapping; |
|
|
|
import org.springframework.web.bind.annotation.RequestMapping; |
|
|
|
import org.springframework.web.bind.annotation.RequestMethod; |
|
|
|
import org.springframework.web.bind.annotation.RequestMethod; |
|
|
|
import org.springframework.web.bind.annotation.RequestParam; |
|
|
|
import org.springframework.web.bind.annotation.RequestParam; |
|
|
|
import org.springframework.web.bind.annotation.RestController; |
|
|
|
import org.springframework.web.bind.annotation.RestController; |
|
|
|
|
|
|
|
|
|
|
|
import javax.servlet.http.HttpSession; |
|
|
|
import javax.servlet.http.HttpSession; |
|
|
|
import java.sql.Connection; |
|
|
|
|
|
|
|
import java.sql.PreparedStatement; |
|
|
|
|
|
|
|
import java.sql.ResultSet; |
|
|
|
|
|
|
|
import java.sql.SQLException; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@RestController |
|
|
|
@RestController |
|
|
|
@RequestMapping(value = "web/auth") |
|
|
|
@RequestMapping(value = "web/auth") |
|
|
|
public class LoginAPI { |
|
|
|
public class LoginAPI { |
|
|
|
|
|
|
|
|
|
|
|
private Logger log = LoggerFactory.getLogger(LoginAPI.class); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@RequestMapping(value = "login", method = RequestMethod.POST) |
|
|
|
@RequestMapping(value = "login", method = RequestMethod.POST) |
|
|
|
public Object doLogin( |
|
|
|
public Object doLogin( |
|
|
|
@RequestParam(name="username", required = true) String userName, |
|
|
|
@RequestParam(name="username", required = true) String userName, |
|
|
|
@RequestParam(name="password", required = true) String password, |
|
|
|
@RequestParam(name="password", required = true) String password, |
|
|
|
HttpSession session |
|
|
|
HttpSession session |
|
|
|
){ |
|
|
|
){ |
|
|
|
String reqIP = HttpReqRespUtils.getClientIpAddressIfServletRequestExist(); |
|
|
|
|
|
|
|
log.info("Login request from {}, username is {}, password length = {}", reqIP, userName, password.length()); |
|
|
|
|
|
|
|
BCryptPasswordEncoder enc = new BCryptPasswordEncoder(Constants.BCRYPT_STRENGTH); |
|
|
|
|
|
|
|
boolean result = false; |
|
|
|
|
|
|
|
try( |
|
|
|
|
|
|
|
Connection conn = DatabaseManager.getInstance().getConnection(); |
|
|
|
|
|
|
|
PreparedStatement pstmt = conn.prepareStatement("SELECT user_id, user_name, password FROM user WHERE user_name = ?"); |
|
|
|
|
|
|
|
){ |
|
|
|
|
|
|
|
pstmt.setString(1, userName); |
|
|
|
|
|
|
|
try(ResultSet rs = pstmt.executeQuery()){ |
|
|
|
|
|
|
|
if(rs.next()){ |
|
|
|
|
|
|
|
log.debug("User found!"); |
|
|
|
|
|
|
|
String passwordHash = rs.getString("password"); |
|
|
|
|
|
|
|
if(enc.matches(password, passwordHash)){ |
|
|
|
|
|
|
|
//Login OK
|
|
|
|
|
|
|
|
result = true; |
|
|
|
|
|
|
|
String tokens [] = passwordHash.split("\\$"); |
|
|
|
|
|
|
|
if(enc.upgradeEncoding(passwordHash) || |
|
|
|
|
|
|
|
(Integer.parseInt(tokens[2])<Constants.BCRYPT_STRENGTH) |
|
|
|
|
|
|
|
){ |
|
|
|
|
|
|
|
log.info("User {} have old version of hash. Update required.", userName); |
|
|
|
|
|
|
|
new Thread(()->{ |
|
|
|
|
|
|
|
try( |
|
|
|
|
|
|
|
Connection connection = DatabaseManager.getInstance().getConnection(); |
|
|
|
|
|
|
|
PreparedStatement psUpd = connection.prepareStatement("UPDATE user SET password = ? WHERE user_name = ?"); |
|
|
|
|
|
|
|
){ |
|
|
|
|
|
|
|
psUpd.setString(1, enc.encode(password)); |
|
|
|
|
|
|
|
psUpd.setString(2, userName); |
|
|
|
|
|
|
|
psUpd.executeUpdate(); |
|
|
|
|
|
|
|
connection.commit(); |
|
|
|
|
|
|
|
}catch (SQLException e){ |
|
|
|
|
|
|
|
log.error(e.getMessage(), e); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}).start(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
session.setAttribute(Constants.SESSION_ATTR_USER_ID, rs.getString("user_id")); |
|
|
|
|
|
|
|
}else{ |
|
|
|
|
|
|
|
//Login failed
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}else{ |
|
|
|
|
|
|
|
log.debug("User not found!"); |
|
|
|
|
|
|
|
//No such user
|
|
|
|
|
|
|
|
//Do a encode to avoid time attack?
|
|
|
|
|
|
|
|
enc.encode(password); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}catch(SQLException e){ |
|
|
|
|
|
|
|
log.error(e.getMessage(), e); |
|
|
|
|
|
|
|
return new Object(){ |
|
|
|
return new Object(){ |
|
|
|
public String getStatus(){return "500";} |
|
|
|
public String getStatus(){return "failed";} |
|
|
|
public String getMessage() {return "Unable to connection to database";} |
|
|
|
public String getMessage() {return "Not implemented";} |
|
|
|
}; |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
if(result){ |
|
|
|
|
|
|
|
return new Object(){ |
|
|
|
|
|
|
|
public String getStatus(){return "200";} |
|
|
|
|
|
|
|
public String getMessage() {return "Login Success!";} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}else{ |
|
|
|
|
|
|
|
return new Object(){ |
|
|
|
|
|
|
|
public String getStatus(){return "401";} |
|
|
|
|
|
|
|
public String getMessage() {return "Username or password incorrect";} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
@RequestMapping(value = "logout") |
|
|
|
@RequestMapping(value = "logout") |
|
|
|
public Object doLogout( |
|
|
|
public Object doLogin( |
|
|
|
HttpSession session |
|
|
|
HttpSession session |
|
|
|
){ |
|
|
|
){ |
|
|
|
session.invalidate(); |
|
|
|
session.invalidate(); |
|
|
|
|