diff --git a/pom.xml b/pom.xml
index d874e04..20964be 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,6 +25,11 @@
org.springframework.boot
spring-boot-starter-web
+
+ org.springframework.security
+ spring-security-core
+
+
org.mariadb.jdbc
diff --git a/src/main/java/org/leolo/nrapi/Constants.java b/src/main/java/org/leolo/nrapi/Constants.java
index a496b70..bc57423 100644
--- a/src/main/java/org/leolo/nrapi/Constants.java
+++ b/src/main/java/org/leolo/nrapi/Constants.java
@@ -2,4 +2,6 @@ package org.leolo.nrapi;
public class Constants {
public static final String REQ_ATTR_USER_ID = "auth-result-user-id";
+
+ public static final String SESSION_ATTR_USER_ID = "auth-result-user-id";
}
diff --git a/src/main/java/org/leolo/nrapi/web/LoginAPI.java b/src/main/java/org/leolo/nrapi/web/LoginAPI.java
index d9dd961..8ee7a68 100644
--- a/src/main/java/org/leolo/nrapi/web/LoginAPI.java
+++ b/src/main/java/org/leolo/nrapi/web/LoginAPI.java
@@ -1,14 +1,21 @@
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.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
@RestController
@RequestMapping(value = "web/auth")
@@ -24,13 +31,68 @@ public class LoginAPI {
){
String reqIP = HttpReqRespUtils.getClientIpAddressIfServletRequestExist();
log.info("Login request from {}, username is {}, password length = {}", reqIP, userName, password.length());
- return new Object(){
- public String getStatus(){return "failed";}
- public String getMessage() {return "Not implemented";}
- };
+ BCryptPasswordEncoder enc = new BCryptPasswordEncoder();
+ 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;
+ if(enc.upgradeEncoding(passwordHash)){
+ 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();
+ }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(){
+ public String getStatus(){return "500";}
+ public String getMessage() {return "Unable to connection to database";}
+ };
+ }
+ 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")
- public Object doLogin(
+ public Object doLogout(
HttpSession session
){
session.invalidate();