Password Config

This commit is contained in:
2025-05-11 20:33:45 +05:00
parent f07097744a
commit 5bf5ac81ea
3 changed files with 76 additions and 174 deletions

14
pom.xml
View File

@ -10,7 +10,7 @@
</parent>
<groupId>org.ccalm</groupId>
<artifactId>jwt</artifactId>
<version>0.0.1-SNAPSHOT</version>
<version>1.0.1</version>
<name>jwt</name>
<description>jwt</description>
<properties>
@ -79,16 +79,7 @@
<artifactId>json</artifactId>
<version>20231013</version>
</dependency>
<!--dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency-->
<!--dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.6</version>
</dependency-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
@ -180,6 +171,7 @@
</dependencies>
<build>
<finalName>org-ccalm-jwt</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>

View File

@ -204,6 +204,23 @@ public class MainController implements ServletContextAware {
return "";
}
//------------------------------------------------------------------------------------------------------------------
public static void validatePassword(String password) throws CustomException {
Translation trt = new Translation("en",null);
if(password.isEmpty())
throw new CustomException(200, 10000,trt.trt(false,"The_password_field_is_empty"),null,false);
if(!Pattern.compile("[0-9]").matcher(password).find())
throw new CustomException(200, 10000,trt.trt(false,"The_password_is_missing_a_number"),null,false);
if(!Pattern.compile("[a-z]").matcher(password).find())
throw new CustomException(200, 10000,trt.trt(false,"The_password_is_missing_a_small_Latin_letter"),null,false);
if (!Pattern.compile("[A-Z]").matcher(password).find())
throw new CustomException(200, 10000,trt.trt(false,"The_password_is_missing_a_big_Latin_letter"),null,false);
if (!Pattern.compile("[_!@#$%^&*]").matcher(password).find())
throw new CustomException(200, 10000,trt.trt(false,"The_password_is_missing_a_special_letter"),null,false);
if (password.length() < 6)
throw new CustomException(200, 10000,trt.trt(false,"The_password_is_less_than_six_characters"),null,false);
}
//------------------------------------------------------------------------------------------------------------------
private PrivateKey getPrivateKey() {
try {
byte[] keyBytes = Base64.getDecoder().decode(this.private_key);
@ -343,20 +360,20 @@ public class MainController implements ServletContextAware {
json.put("error_message","");
json.put("error_marker",(String)null);
String buildDate="";
//String buildVersion="";
String buildVersion="";
try {
InputStream inputStream = MainController.class.getClassLoader().getResourceAsStream("META-INF/build-info.properties");
if (inputStream != null) {
Properties properties = new Properties();
properties.load(inputStream);
buildDate = properties.getProperty("build.time");
//buildVersion = properties.getProperty("build.version");
buildVersion = properties.getProperty("build.version");
}
} catch (Exception e) {
e.printStackTrace();
}
json.put("build_date",buildDate);
//json.put("build_version",buildVersion);
json.put("version",buildVersion);
json.put("name",application_name);
//json.put("active_connections",dataSource.getHikariPoolMXBean().getActiveConnections());
//json.put("idle_connections",dataSource.getHikariPoolMXBean().getIdleConnections());
@ -597,7 +614,7 @@ public class MainController implements ServletContextAware {
byte[] bytes = baos.toByteArray();
json.put("image",Base64.getEncoder().encodeToString(bytes));
} catch (IOException e) {
throw new CustomException(401, 10000, trt.trt(false, "Input_output_error"),UUID.randomUUID().toString(),true);
throw new CustomException(500, 10000, trt.trt(false, "Input_output_error"),UUID.randomUUID().toString(),true);
}
//Формирую JSON токена и шифрую его
@ -674,19 +691,19 @@ public class MainController implements ServletContextAware {
}
if(jToken==null) {
throw new CustomException(401, 10000, trt.trt(false, "Please_send_a_valid_JSON_string_in_your_token"),null,false);
throw new CustomException(200, 10000, trt.trt(false, "Please_send_a_valid_JSON_string_in_your_token"),null,false);
}
if (!verificationModel.getCode().equals(jToken.getString("code"))) {
throw new CustomException(401, 10000, trt.trt(false, "The_code_did_not_match_what_was_specified_in_the_captcha"),null,false);
throw new CustomException(200, 10000, trt.trt(false, "The_code_did_not_match_what_was_specified_in_the_captcha"),null,false);
}
if (jToken.getLong("exp") < (System.currentTimeMillis() / 1000L)) {
throw new CustomException(401, 10000, List.of(trt.trt(false, "Captcha_is_outdated"),trt.trt(false, "Please_update_the_captcha")),null,false);
throw new CustomException(200, 10000, List.of(trt.trt(false, "Captcha_is_outdated"),trt.trt(false, "Please_update_the_captcha")),null,false);
}
if (!Tools.isValidEmail(jToken.getString("email"))) {
throw new CustomException(401, 10000, trt.trt(false, "The_email_field_is_incorrect"),null,false);
throw new CustomException(200, 10000, trt.trt(false, "The_email_field_is_incorrect"),null,false);
}
if (!verificationModel.getEmail().equals(jToken.getString("email"))) {
throw new CustomException(401, 10000, trt.trt(false, "The_email_did_not_match_what_was_specified_in_the_captcha"),null,false);
throw new CustomException(200, 10000, trt.trt(false, "The_email_did_not_match_what_was_specified_in_the_captcha"),null,false);
}
//If this is a repeat authorization, then we inform the client about it
@ -780,7 +797,10 @@ public class MainController implements ServletContextAware {
@Operation(summary = "Create new user account", description = "After creating a user, adding a default user role")
@RequestMapping(value = "/create",method = RequestMethod.POST,produces = "application/json;charset=utf-8")
@ResponseBody
public ResponseEntity<Object> create(@RequestBody NewUserModel newUserModel,@RequestParam(required=false,name="lng",defaultValue="1") String language_id) {
public ResponseEntity<Object> create(
@RequestBody NewUserModel newUserModel,
@RequestParam(required=false,name="lng",defaultValue="1") String language_id
) {
Translation trt = new Translation(language_id,jdbcTemplate);
try{
JSONObject json = new JSONObject();
@ -796,65 +816,41 @@ public class MainController implements ServletContextAware {
if (!Tools.isValidEmail(newUserModel.getEmail())) {
throw new CustomException(400, 10000, trt.trt(false, "The_email_field_is_incorrect"),null,false);
}
if(newUserModel.getCode().length()<3) {
if(newUserModel.getCode().isEmpty()) {
throw new CustomException(400, 10000, trt.trt(false, "The_code_field_is_empty"),null,false);
}
if(newUserModel.getToken().length()<3) {
throw new CustomException(400, 10000, trt.trt(false, "The_token_field_is_empty"),null,false);
}
//if(newUserModel.getToken().length()<3) {
// throw new CustomException(400, 10000, trt.trt(false, "The_token_field_is_empty"),null,false);
//}
validatePassword(newUserModel.getPassword());
//Проверяю что подпись одинакова
String signature1 = afterLast(newUserModel.getToken(), ".");
String payload = beforeFirst(newUserModel.getToken(), ".");
String signature2 = Tools.generateSignature(captchaKey, payload);
if (!signature1.equals(signature2)) {
throw new CustomException(400, 10000, trt.trt(false, "The_signature_did_not_match"),null,false);
}
//Расшифровываю
String sToken = Tools.decryptText(captchaKey,payload);
JSONObject jToken = null;
try {
jToken = new JSONObject(sToken);
} catch (JSONException e) {
logger.error(e);
}
if(jToken==null) {
throw new CustomException(400, 10000, trt.trt(false, "Please_send_a_valid_JSON_string_in_your_token"),null,false);
}
if (!newUserModel.getCode().equals(jToken.getString("code"))) {
throw new CustomException(400, 10000, trt.trt(false, "The_code_did_not_match_what_was_specified_in_the_captcha"),null,false);
}
if (jToken.getLong("exp") < (System.currentTimeMillis() / 1000L)) {
throw new CustomException(400, 10000, List.of(trt.trt(false, "Captcha_is_outdated"),trt.trt(false, "Please_update_the_captcha")),null,false);
}
if (!Tools.isValidEmail(jToken.getString("email"))) {
throw new CustomException(400, 10000, trt.trt(false, "The_email_field_is_incorrect"),null,false);
}
if (!newUserModel.getEmail().equals(jToken.getString("email"))) {
throw new CustomException(400, 10000, trt.trt(false, "The_email_did_not_match_what_was_specified_in_the_captcha"),null,false);
}
//Проверяю существование пользователя с таким email
//We check that the verification code is equal to the one sent to the email
boolean existCode=false;
String sql= """
select * from main._users where email=:email;
select * from users.verification where email=:email and code=:code
""";
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("email", newUserModel.getEmail());
parameters.addValue("code", newUserModel.getCode());
List<String> ret = jdbcTemplate.query(sql, parameters, new DBTools.JsonRowMapper());
for (int i = 0; i < ret.size(); i++) {
existCode = true;
}
if(!existCode){
throw new CustomException(400, 10000, trt.trt(false, "The_email_verification_code_does_not_match_the_expected_code"),null,false);
}
//Check if a user with this email exists
sql = """
select * from main._users where email=:email;
""";
parameters = new MapSqlParameterSource();
parameters.addValue("email", newUserModel.getEmail());
ret = jdbcTemplate.query(sql, parameters, new DBTools.JsonRowMapper());
for (int i = 0; i < ret.size(); i++) {
throw new CustomException(200, 10000, trt.trt(false, "A_user_with_the_same_email_address_already_exists"),null,false);
}
// Генерируем временный пароль
RandomStringGenerator generator = new RandomStringGenerator.Builder()
.withinRange('0', 'z') // диапазон символов (можно настроить)
.filteredBy(c -> Character.isLetterOrDigit(c))
.get();
String password = generator.generate(8);
//Добавляем пользователя
sql = """
insert into main._users(
@ -878,7 +874,7 @@ public class MainController implements ServletContextAware {
pgp_sym_encrypt(CAST(:e_phone AS TEXT), CAST(:key AS TEXT)),
:email,
crypt(:password, gen_salt('bf')),
now()+interval '5 day'
now()+interval '365 day'
) RETURNING id;
""";
parameters = new MapSqlParameterSource();
@ -891,7 +887,7 @@ public class MainController implements ServletContextAware {
parameters.addValue("e_phone",newUserModel.getPhone(), Types.VARCHAR);
parameters.addValue("email",newUserModel.getEmail(), Types.VARCHAR);
parameters.addValue("key",personal_data_key, Types.VARCHAR);
parameters.addValue("password",password, Types.VARCHAR);
parameters.addValue("password",newUserModel.getPassword(), Types.VARCHAR);
ret = jdbcTemplate.query(sql, parameters, new DBTools.JsonRowMapper());
for (int i = 0; i < ret.size(); i++) {
@ -909,8 +905,8 @@ public class MainController implements ServletContextAware {
String html="";
html += "<html><head><title>" + trt.trt(true,"Now_user") + "</title></head><body>";
html += "<h1>" + trt.trt(true, "To_activate_the_user_please_log_in") + ":</h1>";
html += "<a href=\"https://istransit.kz/\">istransit.kz</a><br><br>";
html += trt.trt(true, "To_log_in_please_use_the_following_password") + ": \"<b>" + password + "</b>\"";
html += "<a href=\""+url_main+"\">"+url_main+"</a><br><br>";
html += trt.trt(true, "To_log_in_please_use_the_following_password") + ": \"<b>" + newUserModel.getPassword() + "</b>\"";
html += "</body></html>";
try {
@ -1032,39 +1028,6 @@ public class MainController implements ServletContextAware {
int attempt_limit = bResult.get("attempt_limit");
//attempt_duration=0;
/*String sql = "";
int attempt_count=0, attempt_limit=0, attempt_duration=0;
MapSqlParameterSource parameters = null;
List<String> ret = null;
try {
sql = "select * from main.user_is_blocked(:login,:ip)";
parameters = new MapSqlParameterSource();
parameters.addValue("login", loginModel.getLogin());
parameters.addValue("ip", ipAddress);
ret = jdbcTemplate.query(sql, parameters, new DBTools.JsonRowMapper());
for (int i = 0; i < ret.size(); i++) {
json = new JSONObject(ret.get(i));
if (!json.has("result") || json.getBoolean("result")) {
if(json.getInt("count")==0)
{
throw new CustomException(200, 10000, trt.trt(false, "The_user_account_is_blocked"),null,false);
}else{
throw new CustomException(200, 10000, trt.trt(false, "The_limit_of_authorization_attempts_has_been_exceeded_please_wait_s_minutes"), String.valueOf(json.getInt("limit_duration")),(String)null,false);
}
}
if(json.has("count") && json.has("limit_count") && json.has("limit_duration")) {
attempt_count = json.getInt("count") + 1;
attempt_limit = json.getInt("limit_count");
//attempt_duration = json.getInt("limit_duration");
}
}
}catch (DataAccessException ex){
String uuid = UUID.randomUUID().toString();
logger.error("Функция main.user_is_blocked не вернула результата!", uuid, ex);
throw new CustomException(500, 10000, trt.trt(false, "Error_executing_SQL_query"),uuid,false);
}*/
MapSqlParameterSource parameters = null;
String sql = "";
List<String> ret = null;
@ -1262,7 +1225,6 @@ public class MainController implements ServletContextAware {
//json.put("error_marker",(String)null);
json.put("ip",ipAddress);
String rolesString = json.getJSONObject("roles").getString("value");
JSONArray rolesArray = new JSONArray(rolesString);
json.put("roles",rolesArray);
@ -1298,7 +1260,7 @@ public class MainController implements ServletContextAware {
{
throw new CustomException(200, 10000, trt.trt(false, "The_user_account_is_blocked"),null,false);
}else{
throw new CustomException(200, 10000, java.lang.String.format(trt.trt(false, "The_limit_of_authorization_attempts_has_been_exceeded_please_wait_s_minutes"), json.getInt("limit_duration")),null,false);
throw new CustomException(200, 10000, List.of(trt.trt(false, "The_limit_of_authorization_attempts_has_been_exceeded_please_wait_s_minutes")), List.of(String.valueOf(json.getInt("limit_duration"))),"",false);
}
}
if(json.has("count") && json.has("limit_count") && json.has("limit_duration")) {
@ -1307,6 +1269,8 @@ public class MainController implements ServletContextAware {
//attempt_duration = json.getInt("limit_duration");
}
}
} catch (CustomException e) {
throw e;
}catch (DataAccessException ex){
java.lang.String uuid = UUID.randomUUID().toString();
logger.error(uuid, ex);
@ -1355,38 +1319,6 @@ public class MainController implements ServletContextAware {
int attempt_limit = bResult.get("attempt_limit");
//attempt_duration=0;
/*String sql = "";
int attempt_count=0, attempt_limit=0, attempt_duration=0;
MapSqlParameterSource parameters = null;
List<String> ret = null;
try {
sql = "select * from main.user_is_blocked(:login,:ip)";
parameters = new MapSqlParameterSource();
parameters.addValue("login", loginModel.getLogin());
parameters.addValue("ip", ipAddress);
ret = jdbcTemplate.query(sql, parameters, new DBTools.JsonRowMapper());
for (int i = 0; i < ret.size(); i++) {
json = new JSONObject(ret.get(i));
if (!json.has("result") || json.getBoolean("result")) {
if(json.getInt("count")==0)
{
throw new CustomException(200, 10000, trt.trt(false, "The_user_account_is_blocked"),null,false);
}else{
throw new CustomException(200, 10000, trt.trt(false, "The_limit_of_authorization_attempts_has_been_exceeded_please_wait_s_minutes"), String.valueOf(json.getInt("limit_duration")),(String)null,false);
}
}
if(json.has("count") && json.has("limit_count") && json.has("limit_duration")) {
attempt_count = json.getInt("count");
attempt_limit = json.getInt("limit_count");
//attempt_duration = json.getInt("limit_duration");
}
}
}catch (DataAccessException ex){
String uuid = UUID.randomUUID().toString();
logger.error("Error executing SQL query", uuid, ex);
throw new CustomException(200, 10000, trt.trt(false, "Error_executing_SQL_query"),uuid,false);
}*/
String sql = "";
MapSqlParameterSource parameters = null;
List<String> ret = null;
@ -1754,8 +1686,11 @@ public class MainController implements ServletContextAware {
//------------------------------------------------------------------------------------------------------------------
@RequestMapping(value = "/update",method = {RequestMethod.POST,RequestMethod.GET},produces = "application/json;charset=utf-8")
@ResponseBody
public ResponseEntity<Object> update(HttpServletRequest request, @RequestBody UpdateModel update, @RequestParam(required=false,name="lng",defaultValue="1") String language_id) {
public ResponseEntity<Object> update(
HttpServletRequest request,
@RequestBody UpdateModel update,
@RequestParam(required=false,name="lng",defaultValue="1") String language_id
) {
Translation trt = new Translation(language_id,jdbcTemplate);
try {
JSONObject json = new JSONObject();
@ -1770,19 +1705,8 @@ public class MainController implements ServletContextAware {
throw new CustomException(200, 10000, trt.trt(false,"The_email_field_is_incorrect"),null,false);
if(update.getPassword().isEmpty())
throw new CustomException(200, 10000,trt.trt(false,"The_password_field_is_empty"),null,false);
if(update.getPasswordNew().isEmpty())
throw new CustomException(200, 10000,trt.trt(false,"The_new_password_field_is_empty"),null,false);
if(!Pattern.compile("[0-9]").matcher(update.getPasswordNew()).find())
throw new CustomException(200, 10000,trt.trt(false,"The_password_is_missing_a_number"),null,false);
if(!Pattern.compile("[a-z]").matcher(update.getPasswordNew()).find())
throw new CustomException(200, 10000,trt.trt(false,"The_password_is_missing_a_small_Latin_letter"),null,false);
if (!Pattern.compile("[A-Z]").matcher(update.getPasswordNew()).find())
throw new CustomException(200, 10000,trt.trt(false,"The_password_is_missing_a_big_Latin_letter"),null,false);
if (!Pattern.compile("[_!@#$%^&*]").matcher(update.getPasswordNew()).find())
throw new CustomException(200, 10000,trt.trt(false,"The_password_is_missing_a_special_letter"),null,false);
if (update.getPasswordNew().length() < 6)
throw new CustomException(200, 10000,trt.trt(false,"The_password_is_less_than_six_characters"),null,false);
validatePassword(update.getPasswordNew());
//Проверяем попытки смены пароля (сохраение попыток в функции логина)
String ipAddress = request.getHeader("X-FORWARDED-FOR");
@ -1795,24 +1719,6 @@ public class MainController implements ServletContextAware {
int attempt_limit = bResult.get("attempt_limit");
//attempt_duration=0;
//String sql = "select main.user_is_blocked(:login,:ip) as block";
/*String sql = "select * from main.user_is_blocked(:login,:ip)";
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("login", update.getLogin());
parameters.addValue("ip", ipAddress);
List<String> ret = jdbcTemplate.query(sql, parameters, new DBTools.JsonRowMapper());
JSONObject rows=null;
for (int i = 0; i < ret.size(); i++) {
rows = new JSONObject(ret.get(i));
if(rows.getBoolean("result")) {
throw new CustomException(200, 10000, String.format(trt.trt(false,"The_limit_of_authorization_attempts_has_been_exceeded_please_wait_s_minutes"), 5),null, false);
}
}
if(rows==null) {
logger.error("Функция main.user_is_blocked не вернула результата!");
throw new CustomException(200, 10000, trt.trt(false,"Error_executing_SQL_query"),null, false);
}*/
//Получаю id пользователя TODO should work through the authorization function
String sql = "select id from main._users where del=false and password=crypt(:password, password) and email=:email";
MapSqlParameterSource parameters = new MapSqlParameterSource();
@ -1904,7 +1810,7 @@ public class MainController implements ServletContextAware {
}
}
}
return new ResponseEntity<>(new ErrorResponseModel(200, 0), HttpStatus.OK);
return new ResponseEntity<>(new ErrorResponseModel(200, 0,"",""), HttpStatus.OK);
} catch (CustomException e) {
if(e.isSaveToLog()) {
logger.error(e.getErrorMarker(), e);

View File

@ -31,6 +31,10 @@ public class NewUserModel {
private String code;
@JsonProperty("token")
private String token;
@JsonProperty("password")
private String password;
/*
public String getCountry() {
if(country==null) return "";