Added authorization check

This commit is contained in:
Mikhail Trofimov 2025-06-04 13:36:44 +03:00
parent c0f855c2a0
commit 62e60dd909
4 changed files with 75 additions and 6 deletions

View file

@ -1,24 +1,31 @@
package ru.nbch.credit_tracker.facade; package ru.nbch.credit_tracker.facade;
import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import ru.nbch.credit_tracker.enums.SignalError; import ru.nbch.credit_tracker.enums.SignalError;
import ru.nbch.credit_tracker.service.FailureAnswerGenerator; import ru.nbch.credit_tracker.service.FailureAnswerGenerator;
import ru.nbch.credit_tracker.service.scoring.AuthorizationService;
import java.io.IOException; import java.io.IOException;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
@Slf4j
@Service @Service
public class SignalFacade { public class SignalFacade {
private static final long MAX_XML_FILE_SIZE = 2L * 1024 * 1024 * 1024; private static final long MAX_XML_FILE_SIZE = 2L * 1024 * 1024 * 1024;
private final AuthorizationService authorizationService;
private final FailureAnswerGenerator failureAnswerGenerator; private final FailureAnswerGenerator failureAnswerGenerator;
public SignalFacade(FailureAnswerGenerator failureAnswerGenerator) { public SignalFacade(AuthorizationService authorizationService,
FailureAnswerGenerator failureAnswerGenerator) {
this.authorizationService = authorizationService;
this.failureAnswerGenerator = failureAnswerGenerator; this.failureAnswerGenerator = failureAnswerGenerator;
} }
@ -64,12 +71,15 @@ public class SignalFacade {
} }
AuthInfoData authInfoData = parseAuthInfo(zipInputStream); // TODO authorize AuthInfoData authInfoData = parseAuthInfo(zipInputStream);
if (!authorizationService.hasAuthorization(authInfoData.getUserId(), authInfoData.getPassword())) {
return ResponseEntity.badRequest().body(failureAnswerGenerator.generateFailureAnswer(SignalError.ERROR_005));
}
// TODO process xml file // TODO process xml file
} catch (IOException e) { } catch (Exception e) {
log.error(e.getMessage(), e);
return ResponseEntity.internalServerError().body(failureAnswerGenerator.generateFailureAnswer(SignalError.ERROR_001)); return ResponseEntity.internalServerError().body(failureAnswerGenerator.generateFailureAnswer(SignalError.ERROR_001));
} }
@ -84,13 +94,14 @@ public class SignalFacade {
} }
private AuthInfoData parseAuthInfo(ZipInputStream zipInputStream) throws IOException { private AuthInfoData parseAuthInfo(ZipInputStream zipInputStream) throws IOException {
return new AuthInfoData(); return new AuthInfoData("0001XX000001", "test"); // TODO parse
} }
@Getter @Getter
@Setter @Setter
@AllArgsConstructor
private static class AuthInfoData { private static class AuthInfoData {
private String username; private String userId;
private String password; private String password;
} }
} }

View file

@ -0,0 +1,11 @@
package ru.nbch.credit_tracker.mapper.scoring;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface ModelUsersMapper {
boolean hasAuthorization(@Param("userId") String userId, @Param("password") String password, @Param("productCode") String productCode);
}

View file

@ -0,0 +1,34 @@
package ru.nbch.credit_tracker.service.scoring;
import jakarta.xml.bind.DatatypeConverter;
import org.springframework.stereotype.Service;
import ru.nbch.credit_tracker.mapper.scoring.ModelUsersMapper;
import java.security.MessageDigest;
@Service
public class AuthorizationService {
private static final String SGNL_CODE = "SGNL";
private static final String SALT = "-*-XUSER_"; // TODO move salt to props?
private final ModelUsersMapper mapper;
public AuthorizationService(ModelUsersMapper mapper) {
this.mapper = mapper;
}
public boolean hasAuthorization(String userId, String password) throws Exception {
String hashedPassword = hashPassword(password);
return mapper.hasAuthorization(userId, hashedPassword, SGNL_CODE);
}
private String hashPassword(String password) throws Exception {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest((SALT + password).getBytes("windows-1251"));
return DatatypeConverter.printHexBinary(messageDigest).toLowerCase();
} catch (Exception e) {
throw new Exception("Unable to hash password", e);
}
}
}

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="ru.nbch.credit_tracker.mapper.scoring.ModelUsersMapper">
<select id="hasAuthorization" resultType="boolean">
SELECT COUNT(*) > 0
FROM XMODEL_USERS
WHERE USERNAME = #{userId} AND PASSWORD = #{password} AND PRODUCT = #{productCode}
</select>
</mapper>