Merge pull request 'Add PWs' (#61) from passwords into master
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Reviewed-on: #61 Reviewed-by: Lixfel <lixfel@steamwar.de>
Dieser Commit ist enthalten in:
Commit
e7952685d2
@ -21,17 +21,32 @@ package de.steamwar.sql;
|
|||||||
|
|
||||||
import de.steamwar.sql.internal.*;
|
import de.steamwar.sql.internal.*;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKeyFactory;
|
||||||
|
import javax.crypto.spec.PBEKeySpec;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class SteamwarUser {
|
public class SteamwarUser {
|
||||||
|
private static final SecureRandom random = new SecureRandom();
|
||||||
|
private static final SecretKeyFactory factory;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
new SqlTypeMapper<>(UUID.class, "CHAR(36)", (rs, identifier) -> UUID.fromString(rs.getString(identifier)), (st, index, value) -> st.setString(index, value.toString()));
|
try {
|
||||||
|
factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new SecurityException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
new SqlTypeMapper<>(UUID.class, "CHAR(36)", (rs, identifier) -> UUID.fromString(rs.getString(identifier)), (st, index, value) -> st.setString(index, value.toString()));
|
||||||
new SqlTypeMapper<>(Locale.class, "VARCHAR(32)", (rs, identifier) -> {
|
new SqlTypeMapper<>(Locale.class, "VARCHAR(32)", (rs, identifier) -> {
|
||||||
String l = rs.getString(identifier);
|
String l = rs.getString(identifier);
|
||||||
return l != null ? Locale.forLanguageTag(l) : null;
|
return l != null ? Locale.forLanguageTag(l) : null;
|
||||||
@ -49,6 +64,7 @@ public class SteamwarUser {
|
|||||||
private static final SelectStatement<SteamwarUser> getServerTeam = new SelectStatement<>(table, "SELECT * FROM UserData WHERE UserGroup != 'Member' AND UserGroup != 'YouTuber'");
|
private static final SelectStatement<SteamwarUser> getServerTeam = new SelectStatement<>(table, "SELECT * FROM UserData WHERE UserGroup != 'Member' AND UserGroup != 'YouTuber'");
|
||||||
|
|
||||||
private static final Statement updateName = table.update(Table.PRIMARY, "UserName");
|
private static final Statement updateName = table.update(Table.PRIMARY, "UserName");
|
||||||
|
private static final Statement updatePassword = table.update(Table.PRIMARY, "Password");
|
||||||
private static final Statement updateLocale = table.update(Table.PRIMARY, "Locale", "ManualLocale");
|
private static final Statement updateLocale = table.update(Table.PRIMARY, "Locale", "ManualLocale");
|
||||||
private static final Statement updateTeam = table.update(Table.PRIMARY, "Team");
|
private static final Statement updateTeam = table.update(Table.PRIMARY, "Team");
|
||||||
private static final Statement updateLeader = table.update(Table.PRIMARY, "Leader");
|
private static final Statement updateLeader = table.update(Table.PRIMARY, "Leader");
|
||||||
@ -110,7 +126,7 @@ public class SteamwarUser {
|
|||||||
if (user != null) {
|
if (user != null) {
|
||||||
if (!user.userName.equals(name)) {
|
if (!user.userName.equals(name)) {
|
||||||
updateName.update(name, user.id);
|
updateName.update(name, user.id);
|
||||||
nameUpdate.accept(user.userName, name);
|
nameUpdate.accept(user.userName, name);
|
||||||
user.userName = name;
|
user.userName = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +164,9 @@ public class SteamwarUser {
|
|||||||
@Getter
|
@Getter
|
||||||
@Field
|
@Field
|
||||||
private String userName;
|
private String userName;
|
||||||
@Getter
|
@Field(nullable = true)
|
||||||
|
private String password;
|
||||||
|
@Getter
|
||||||
@Field(def = "0")
|
@Field(def = "0")
|
||||||
private int team;
|
private int team;
|
||||||
@Getter
|
@Getter
|
||||||
@ -166,10 +184,11 @@ public class SteamwarUser {
|
|||||||
private Set<UserPerm> permissions = null;
|
private Set<UserPerm> permissions = null;
|
||||||
private UserPerm.Prefix prefix = null;
|
private UserPerm.Prefix prefix = null;
|
||||||
|
|
||||||
public SteamwarUser(int id, UUID uuid, String userName, int team, boolean leader, Locale locale, boolean manualLocale, Long discordId) {
|
public SteamwarUser(int id, UUID uuid, String userName, String password, int team, boolean leader, Locale locale, boolean manualLocale, Long discordId) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.userName = userName;
|
this.userName = userName;
|
||||||
|
this.password = password;
|
||||||
this.team = team;
|
this.team = team;
|
||||||
this.leader = leader;
|
this.leader = leader;
|
||||||
this.locale = locale;
|
this.locale = locale;
|
||||||
@ -280,6 +299,52 @@ public class SteamwarUser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
try {
|
||||||
|
byte[] salt = new byte[16];
|
||||||
|
random.nextBytes(salt);
|
||||||
|
String saltString = Base64.getEncoder().encodeToString(salt);
|
||||||
|
|
||||||
|
byte[] hash = generateHash(password, salt);
|
||||||
|
String hashString = Base64.getEncoder().encodeToString(hash);
|
||||||
|
this.password = hashString + ":" + saltString;
|
||||||
|
updatePassword.update(this.password, id);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new SecurityException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean verifyPassword(String password) {
|
||||||
|
try {
|
||||||
|
if (this.password == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] parts = this.password.split(":");
|
||||||
|
if (parts.length != 2) {
|
||||||
|
SQLConfig.impl.getLogger().log(Level.SEVERE ,"Invalid password hash for user {0} ({1})", new Object[]{userName, id});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String hashString = parts[0];
|
||||||
|
byte[] realHash = Base64.getDecoder().decode(hashString);
|
||||||
|
String saltString = parts[1];
|
||||||
|
byte[] salt = Base64.getDecoder().decode(saltString);
|
||||||
|
byte[] hash = generateHash(password, salt);
|
||||||
|
return Arrays.equals(realHash, hash);
|
||||||
|
} catch (Exception e) {
|
||||||
|
SQLConfig.impl.getLogger().log(Level.SEVERE, "Error while verifying password for user " + userName + " (" + id + ")", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] generateHash(String password, byte[] salt)
|
||||||
|
throws InvalidKeySpecException {
|
||||||
|
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 512);
|
||||||
|
return factory.generateSecret(spec).getEncoded();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void initPunishments() {
|
private void initPunishments() {
|
||||||
if(punishments != null)
|
if(punishments != null)
|
||||||
return;
|
return;
|
||||||
|
@ -25,9 +25,13 @@ import de.steamwar.sql.internal.Statement;
|
|||||||
import de.steamwar.sql.internal.Table;
|
import de.steamwar.sql.internal.Table;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
|
import java.util.Base64;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@ -41,6 +45,29 @@ public class Token {
|
|||||||
private static final SelectStatement<Token> getHash = table.selectFields("hash");
|
private static final SelectStatement<Token> getHash = table.selectFields("hash");
|
||||||
private static final Statement delete = table.delete(Table.PRIMARY);
|
private static final Statement delete = table.delete(Table.PRIMARY);
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private static String getHash(String code) {
|
||||||
|
return Base64.getEncoder().encodeToString(MessageDigest.getInstance("SHA-512").digest(code.getBytes()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public static String createToken(String name, SteamwarUser owner) {
|
||||||
|
SecureRandom random = new SecureRandom();
|
||||||
|
byte[] bytes = new byte[20];
|
||||||
|
random.nextBytes(bytes);
|
||||||
|
|
||||||
|
String code = Base64.getEncoder().encodeToString(bytes);
|
||||||
|
|
||||||
|
String hash = getHash(code);
|
||||||
|
create(name, owner, hash);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Token getTokenByCode(String code) {
|
||||||
|
String hash = getHash(code);
|
||||||
|
return get(hash);
|
||||||
|
}
|
||||||
|
|
||||||
public static Token create(String name, SteamwarUser owner, String hash) {
|
public static Token create(String name, SteamwarUser owner, String hash) {
|
||||||
int id = insert.insertGetKey(name, owner, hash);
|
int id = insert.insertGetKey(name, owner, hash);
|
||||||
return get(id);
|
return get(id);
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren