From a42c41540472aacb92ce6dbc72e318a75a12b9db Mon Sep 17 00:00:00 2001 From: Me Car Date: Tue, 5 Jan 2016 02:16:17 +0900 Subject: [PATCH 1/5] Rename connection.password to connection.adminpassword. --- Mage.Common/src/mage/remote/Connection.java | 10 +++++----- Mage.Common/src/mage/remote/SessionImpl.java | 4 ++-- .../main/java/mage/server/console/ConnectDialog.java | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Mage.Common/src/mage/remote/Connection.java b/Mage.Common/src/mage/remote/Connection.java index 0c4e86c827..ddb78d413c 100644 --- a/Mage.Common/src/mage/remote/Connection.java +++ b/Mage.Common/src/mage/remote/Connection.java @@ -44,7 +44,7 @@ public class Connection { private String host; private int port; private String username; - private String password; + private String adminPassword; private ProxyType proxyType; private String proxyHost; private int proxyPort; @@ -164,12 +164,12 @@ public class Connection { this.username = username; } - public String getPassword() { - return password; + public String getAdminPassword() { + return adminPassword; } - public void setPassword(String password) { - this.password = password; + public void setAdminPassword(String adminPassword) { + this.adminPassword = adminPassword; } public String getProxyHost() { diff --git a/Mage.Common/src/mage/remote/SessionImpl.java b/Mage.Common/src/mage/remote/SessionImpl.java index 3b4036d4c2..5045023cea 100644 --- a/Mage.Common/src/mage/remote/SessionImpl.java +++ b/Mage.Common/src/mage/remote/SessionImpl.java @@ -278,14 +278,14 @@ public class SessionImpl implements Session { this.sessionId = callbackClient.getSessionId(); boolean registerResult; - if (connection.getPassword() == null) { + if (connection.getAdminPassword() == null) { // for backward compatibility. don't remove twice call - first one does nothing but for version checking registerResult = server.registerClient(connection.getUsername(), sessionId, client.getVersion()); if (registerResult) { server.setUserData(connection.getUsername(), sessionId, connection.getUserData()); } } else { - registerResult = server.registerAdmin(connection.getPassword(), sessionId, client.getVersion()); + registerResult = server.registerAdmin(connection.getAdminPassword(), sessionId, client.getVersion()); } if (registerResult) { sessionState = SessionState.CONNECTED; diff --git a/Mage.Server.Console/src/main/java/mage/server/console/ConnectDialog.java b/Mage.Server.Console/src/main/java/mage/server/console/ConnectDialog.java index 127efc1b71..6a4b6e8620 100644 --- a/Mage.Server.Console/src/main/java/mage/server/console/ConnectDialog.java +++ b/Mage.Server.Console/src/main/java/mage/server/console/ConnectDialog.java @@ -413,7 +413,7 @@ public class ConnectDialog extends JDialog { connection = new Connection(); connection.setHost(this.txtServer.getText()); connection.setPort(Integer.valueOf(this.txtPort.getText())); - connection.setPassword(new String(txtPassword.getPassword())); + connection.setAdminPassword(new String(txtPassword.getPassword())); connection.setUsername("Admin"); connection.setProxyType((ProxyType) this.cbProxyType.getSelectedItem()); if (!this.cbProxyType.getSelectedItem().equals(ProxyType.NONE)) { From ea5abfe5780574ae3a3567d7880bf61e868cd020 Mon Sep 17 00:00:00 2001 From: Me Car Date: Tue, 5 Jan 2016 02:10:43 +0900 Subject: [PATCH 2/5] Add password input box --- .../mage/client/dialog/ConnectDialog.form | 17 ++++++++ .../mage/client/dialog/ConnectDialog.java | 39 +++++++++++++++---- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form index e84af7c5e3..5e7ce33c21 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form @@ -40,6 +40,7 @@ + @@ -53,6 +54,7 @@ + @@ -85,6 +87,11 @@ + + + + + @@ -152,6 +159,16 @@ + + + + + + + + + + diff --git a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java index ba8cbb2bf6..2975085a91 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java @@ -90,15 +90,17 @@ public class ConnectDialog extends MageDialog { public ConnectDialog() { initComponents(); - this.txtUserName.addActionListener(connectAction); this.txtServer.addActionListener(connectAction); this.txtPort.addActionListener(connectAction); + this.txtUserName.addActionListener(connectAction); + this.txtPassword.addActionListener(connectAction); } public void showDialog() { this.txtServer.setText(MageFrame.getPreferences().get("serverAddress", Config.serverName)); this.txtPort.setText(MageFrame.getPreferences().get("serverPort", Integer.toString(Config.port))); this.txtUserName.setText(MageFrame.getPreferences().get("userName", "")); + this.txtPassword.setText(MageFrame.getPreferences().get("password", "")); this.chkAutoConnect.setSelected(Boolean.parseBoolean(MageFrame.getPreferences().get(KEY_CONNECT_AUTO_CONNECT, "false"))); this.chkForceUpdateDB.setSelected(false); // has always to be set manually to force comparison @@ -120,6 +122,7 @@ public class ConnectDialog extends MageDialog { MageFrame.getPreferences().put("serverAddress", txtServer.getText().trim()); MageFrame.getPreferences().put("serverPort", txtPort.getText().trim()); MageFrame.getPreferences().put("userName", txtUserName.getText().trim()); + MageFrame.getPreferences().put("password", txtPassword.getText().trim()); MageFrame.getPreferences().put(KEY_CONNECT_AUTO_CONNECT, Boolean.toString(chkAutoConnect.isSelected())); } @@ -139,6 +142,8 @@ public class ConnectDialog extends MageDialog { txtPort = new javax.swing.JTextField(); lblUserName = new javax.swing.JLabel(); txtUserName = new javax.swing.JTextField(); + lblPassword = new javax.swing.JLabel(); + txtPassword = new javax.swing.JTextField(); lblFlag = new javax.swing.JLabel(); cbFlag = new mage.client.util.gui.countryBox.CountryComboBox(); chkAutoConnect = new javax.swing.JCheckBox(); @@ -175,6 +180,9 @@ public class ConnectDialog extends MageDialog { lblUserName.setLabelFor(txtUserName); lblUserName.setText("User name:"); + lblPassword.setLabelFor(txtPassword); + lblPassword.setText("Password:"); + lblFlag.setLabelFor(txtUserName); lblFlag.setText("User flag:"); @@ -234,7 +242,8 @@ public class ConnectDialog extends MageDialog { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(lblPort) .addComponent(lblServer) - .addComponent(lblUserName)) + .addComponent(lblUserName) + .addComponent(lblPassword)) .addComponent(lblFlag, javax.swing.GroupLayout.Alignment.TRAILING)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -245,7 +254,8 @@ public class ConnectDialog extends MageDialog { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) .addComponent(txtServer, javax.swing.GroupLayout.DEFAULT_SIZE, 286, Short.MAX_VALUE) .addComponent(txtPort, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(txtUserName)) + .addComponent(txtUserName) + .addComponent(txtPassword)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(btnFind)) .addComponent(chkForceUpdateDB, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) @@ -269,6 +279,10 @@ public class ConnectDialog extends MageDialog { .addComponent(txtUserName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lblUserName)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblPassword)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(lblFlag, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(cbFlag, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) @@ -302,10 +316,6 @@ public class ConnectDialog extends MageDialog { private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnConnectActionPerformed - if (txtUserName.getText().isEmpty()) { - JOptionPane.showMessageDialog(rootPane, "Please provide a user name"); - return; - } if (txtServer.getText().trim().isEmpty()) { JOptionPane.showMessageDialog(rootPane, "Please provide a server address"); return; @@ -314,6 +324,14 @@ public class ConnectDialog extends MageDialog { JOptionPane.showMessageDialog(rootPane, "Please provide a port number"); return; } + if (txtUserName.getText().isEmpty()) { + JOptionPane.showMessageDialog(rootPane, "Please provide a user name"); + return; + } + if (txtPassword.getText().isEmpty()) { + JOptionPane.showMessageDialog(rootPane, "Please provide a password"); + return; + } if (Integer.valueOf(txtPort.getText()) < 1 || Integer.valueOf(txtPort.getText()) > 65535) { JOptionPane.showMessageDialog(rootPane, "Invalid port number"); txtPort.setText(MageFrame.getPreferences().get("serverPort", Integer.toString(Config.port))); @@ -327,6 +345,7 @@ public class ConnectDialog extends MageDialog { connection.setHost(this.txtServer.getText().trim()); connection.setPort(Integer.valueOf(this.txtPort.getText().trim())); connection.setUsername(this.txtUserName.getText().trim()); + connection.setPassword(this.txtPassword.getText().trim()); connection.setForceDBComparison(this.chkForceUpdateDB.isSelected()); MageFrame.getPreferences().put(KEY_CONNECT_FLAG, ((CountryItemEditor) cbFlag.getEditor()).getImageItem()); @@ -541,6 +560,10 @@ public class ConnectDialog extends MageDialog { // TODO add your handling code here: }//GEN-LAST:event_chkForceUpdateDBActionPerformed + private void txtUserNameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtUserNameActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_txtUserNameActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton btnCancel; private javax.swing.JButton btnConnect; @@ -550,10 +573,12 @@ public class ConnectDialog extends MageDialog { private javax.swing.JCheckBox chkForceUpdateDB; private javax.swing.JButton jProxySettingsButton; private javax.swing.JLabel lblFlag; + private javax.swing.JLabel lblPassword; private javax.swing.JLabel lblPort; private javax.swing.JLabel lblServer; private javax.swing.JLabel lblStatus; private javax.swing.JLabel lblUserName; + private javax.swing.JTextField txtPassword; private javax.swing.JTextField txtPort; private javax.swing.JTextField txtServer; private javax.swing.JTextField txtUserName; From 33330e934512be53553b5674b4fe5acc9934964d Mon Sep 17 00:00:00 2001 From: Me Car Date: Tue, 5 Jan 2016 02:12:12 +0900 Subject: [PATCH 3/5] change the type to password --- Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form index 5e7ce33c21..f6423007f7 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form @@ -167,7 +167,7 @@ - + From d0ea7d9c378eb323b1372e83ce752c2c9065f385 Mon Sep 17 00:00:00 2001 From: Me Car Date: Tue, 5 Jan 2016 02:40:05 +0900 Subject: [PATCH 4/5] Transfer password. --- Mage.Common/src/mage/interfaces/MageServer.java | 2 +- Mage.Common/src/mage/remote/Connection.java | 9 +++++++++ Mage.Common/src/mage/remote/SessionImpl.java | 2 +- .../src/main/java/mage/server/MageServerImpl.java | 14 +++++++------- Mage.Server/src/main/java/mage/server/Session.java | 7 ++++--- .../src/main/java/mage/server/SessionManager.java | 4 ++-- 6 files changed, 24 insertions(+), 14 deletions(-) diff --git a/Mage.Common/src/mage/interfaces/MageServer.java b/Mage.Common/src/mage/interfaces/MageServer.java index 4d30942a1e..75baad0e6a 100644 --- a/Mage.Common/src/mage/interfaces/MageServer.java +++ b/Mage.Common/src/mage/interfaces/MageServer.java @@ -56,7 +56,7 @@ import mage.view.UserView; public interface MageServer { // connection methods - boolean registerClient(String userName, String sessionId, MageVersion version) throws MageException; + boolean registerClient(String userName, String password, String sessionId, MageVersion version) throws MageException; boolean registerAdmin(String password, String sessionId, MageVersion version) throws MageException; // Not used diff --git a/Mage.Common/src/mage/remote/Connection.java b/Mage.Common/src/mage/remote/Connection.java index ddb78d413c..4b68eb2560 100644 --- a/Mage.Common/src/mage/remote/Connection.java +++ b/Mage.Common/src/mage/remote/Connection.java @@ -44,6 +44,7 @@ public class Connection { private String host; private int port; private String username; + private String password; private String adminPassword; private ProxyType proxyType; private String proxyHost; @@ -164,6 +165,14 @@ public class Connection { this.username = username; } + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + public String getAdminPassword() { return adminPassword; } diff --git a/Mage.Common/src/mage/remote/SessionImpl.java b/Mage.Common/src/mage/remote/SessionImpl.java index 5045023cea..a75ab5ab49 100644 --- a/Mage.Common/src/mage/remote/SessionImpl.java +++ b/Mage.Common/src/mage/remote/SessionImpl.java @@ -280,7 +280,7 @@ public class SessionImpl implements Session { boolean registerResult; if (connection.getAdminPassword() == null) { // for backward compatibility. don't remove twice call - first one does nothing but for version checking - registerResult = server.registerClient(connection.getUsername(), sessionId, client.getVersion()); + registerResult = server.registerClient(connection.getUsername(), connection.getPassword(), sessionId, client.getVersion()); if (registerResult) { server.setUserData(connection.getUsername(), sessionId, connection.getUserData()); } diff --git a/Mage.Server/src/main/java/mage/server/MageServerImpl.java b/Mage.Server/src/main/java/mage/server/MageServerImpl.java index 46c6ce0aad..2405d45f6b 100644 --- a/Mage.Server/src/main/java/mage/server/MageServerImpl.java +++ b/Mage.Server/src/main/java/mage/server/MageServerImpl.java @@ -96,24 +96,24 @@ public class MageServerImpl implements MageServer { private static final Logger logger = Logger.getLogger(MageServerImpl.class); private static final ExecutorService callExecutor = ThreadExecutor.getInstance().getCallExecutor(); - private final String password; + private final String adminPassword; private final boolean testMode; - public MageServerImpl(String password, boolean testMode) { - this.password = password; + public MageServerImpl(String adminPassword, boolean testMode) { + this.adminPassword = adminPassword; this.testMode = testMode; ServerMessagesUtil.getInstance().getMessages(); } @Override - public boolean registerClient(String userName, String sessionId, MageVersion version) throws MageException { + public boolean registerClient(String userName, String password, String sessionId, MageVersion version) throws MageException { try { if (version.compareTo(Main.getVersion()) != 0) { logger.info("MageVersionException: userName=" + userName + ", version=" + version); LogServiceImpl.instance.log(LogKeys.KEY_WRONG_VERSION, userName, version.toString(), Main.getVersion().toString(), sessionId); throw new MageVersionException(version, Main.getVersion()); } - return SessionManager.getInstance().registerUser(sessionId, userName); + return SessionManager.getInstance().registerUser(sessionId, userName, password); } catch (MageException ex) { if (ex instanceof MageVersionException) { throw (MageVersionException) ex; @@ -134,12 +134,12 @@ public class MageServerImpl implements MageServer { } @Override - public boolean registerAdmin(String password, String sessionId, MageVersion version) throws MageException { + public boolean registerAdmin(String adminPassword, String sessionId, MageVersion version) throws MageException { try { if (version.compareTo(Main.getVersion()) != 0) { throw new MageException("Wrong client version " + version + ", expecting version " + Main.getVersion()); } - if (!password.equals(this.password)) { + if (!adminPassword.equals(this.adminPassword)) { throw new MageException("Wrong password"); } return SessionManager.getInstance().registerAdmin(sessionId); diff --git a/Mage.Server/src/main/java/mage/server/Session.java b/Mage.Server/src/main/java/mage/server/Session.java index 9a03b6e0e0..9e49fcd24b 100644 --- a/Mage.Server/src/main/java/mage/server/Session.java +++ b/Mage.Server/src/main/java/mage/server/Session.java @@ -74,8 +74,8 @@ public class Session { this.lock = new ReentrantLock(); } - public String registerUser(String userName) throws MageException { - String returnMessage = registerUserHandling(userName); + public String registerUser(String userName, String password) throws MageException { + String returnMessage = registerUserHandling(userName, password); if (returnMessage != null) { sendErrorMessageToClient(returnMessage); } @@ -86,7 +86,7 @@ public class Session { return lock.isLocked(); } - public String registerUserHandling(String userName) throws MageException { + public String registerUserHandling(String userName, String password) throws MageException { this.isAdmin = false; if (userName.equals("Admin")) { return "User name Admin already in use"; @@ -102,6 +102,7 @@ public class Session { if (m.find()) { return "User name '" + userName + "' includes not allowed characters: use a-z, A-Z and 0-9"; } + // TODO: Do an authentication with userName and password. User user = UserManager.getInstance().createUser(userName, host); boolean reconnect = false; if (user == null) { // user already exists diff --git a/Mage.Server/src/main/java/mage/server/SessionManager.java b/Mage.Server/src/main/java/mage/server/SessionManager.java index d7a6db388e..bdfbce5a7d 100644 --- a/Mage.Server/src/main/java/mage/server/SessionManager.java +++ b/Mage.Server/src/main/java/mage/server/SessionManager.java @@ -70,10 +70,10 @@ public class SessionManager { sessions.put(sessionId, session); } - public boolean registerUser(String sessionId, String userName) throws MageException { + public boolean registerUser(String sessionId, String userName, String password) throws MageException { Session session = sessions.get(sessionId); if (session != null) { - String returnMessage = session.registerUser(userName); + String returnMessage = session.registerUser(userName, password); if (returnMessage == null) { LogServiceImpl.instance.log(LogKeys.KEY_USER_CONNECTED, userName, session.getHost(), sessionId); From 32b4675f131910ca4bfc10b73889fed729eba430 Mon Sep 17 00:00:00 2001 From: Me Car Date: Tue, 5 Jan 2016 03:48:43 +0900 Subject: [PATCH 5/5] Integrate Shiro. --- .../mage/client/dialog/ConnectDialog.java | 20 +++- Mage.Server/pom.xml | 6 ++ .../main/java/mage/server/AuthorizedUser.java | 52 ++++++++++ .../mage/server/AuthorizedUserRepository.java | 97 +++++++++++++++++++ .../src/main/java/mage/server/Session.java | 11 +++ 5 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 Mage.Server/src/main/java/mage/server/AuthorizedUser.java create mode 100644 Mage.Server/src/main/java/mage/server/AuthorizedUserRepository.java diff --git a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java index 2975085a91..0945bf67d3 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java @@ -143,7 +143,7 @@ public class ConnectDialog extends MageDialog { lblUserName = new javax.swing.JLabel(); txtUserName = new javax.swing.JTextField(); lblPassword = new javax.swing.JLabel(); - txtPassword = new javax.swing.JTextField(); + txtPassword = new javax.swing.JPasswordField(); lblFlag = new javax.swing.JLabel(); cbFlag = new mage.client.util.gui.countryBox.CountryComboBox(); chkAutoConnect = new javax.swing.JCheckBox(); @@ -180,9 +180,21 @@ public class ConnectDialog extends MageDialog { lblUserName.setLabelFor(txtUserName); lblUserName.setText("User name:"); + txtUserName.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + txtUserNameActionPerformed(evt); + } + }); + lblPassword.setLabelFor(txtPassword); lblPassword.setText("Password:"); + txtPassword.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + txtPasswordActionPerformed(evt); + } + }); + lblFlag.setLabelFor(txtUserName); lblFlag.setText("User flag:"); @@ -564,6 +576,10 @@ public class ConnectDialog extends MageDialog { // TODO add your handling code here: }//GEN-LAST:event_txtUserNameActionPerformed + private void txtPasswordActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtPasswordActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_txtPasswordActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton btnCancel; private javax.swing.JButton btnConnect; @@ -578,7 +594,7 @@ public class ConnectDialog extends MageDialog { private javax.swing.JLabel lblServer; private javax.swing.JLabel lblStatus; private javax.swing.JLabel lblUserName; - private javax.swing.JTextField txtPassword; + private javax.swing.JPasswordField txtPassword; private javax.swing.JTextField txtPort; private javax.swing.JTextField txtServer; private javax.swing.JTextField txtUserName; diff --git a/Mage.Server/pom.xml b/Mage.Server/pom.xml index dabb43df49..80916da83e 100644 --- a/Mage.Server/pom.xml +++ b/Mage.Server/pom.xml @@ -148,6 +148,12 @@ ${project.version} runtime + + org.apache.shiro + shiro-core + 1.2.4 + jar + diff --git a/Mage.Server/src/main/java/mage/server/AuthorizedUser.java b/Mage.Server/src/main/java/mage/server/AuthorizedUser.java new file mode 100644 index 0000000000..d3a678ccd1 --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/AuthorizedUser.java @@ -0,0 +1,52 @@ +package mage.server; + +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.SimpleAuthenticationInfo; +import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.authc.credential.HashedCredentialsMatcher; +import org.apache.shiro.util.ByteSource; +import org.apache.shiro.codec.Base64; +import org.apache.shiro.crypto.hash.Hash; + +@DatabaseTable(tableName = "authorized_user") +public class AuthorizedUser { + + @DatabaseField(indexName = "name_index") + protected String name; + + @DatabaseField + protected String password; + + @DatabaseField + protected String salt; + + @DatabaseField + protected String hashAlgorithm; + + @DatabaseField + protected int hashIterations; + + public AuthorizedUser() { + } + + public AuthorizedUser(String name, Hash hash) { + this.name = name; + this.password = hash.toBase64(); + this.salt = hash.getSalt().toBase64(); + this.hashAlgorithm = hash.getAlgorithmName(); + this.hashIterations = hash.getIterations(); + } + + public boolean doCredentialsMatch(String name, String password) { + HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(this.hashAlgorithm); + matcher.setHashIterations(this.hashIterations); + AuthenticationToken token = new UsernamePasswordToken(name, password); + AuthenticationInfo info = new SimpleAuthenticationInfo(this.name, + ByteSource.Util.bytes(Base64.decode(this.password)), + ByteSource.Util.bytes(Base64.decode(this.salt)), ""); + return matcher.doCredentialsMatch(token, info); + } +} diff --git a/Mage.Server/src/main/java/mage/server/AuthorizedUserRepository.java b/Mage.Server/src/main/java/mage/server/AuthorizedUserRepository.java new file mode 100644 index 0000000000..551c8cb6fc --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/AuthorizedUserRepository.java @@ -0,0 +1,97 @@ +package mage.server; + +import com.j256.ormlite.dao.Dao; +import com.j256.ormlite.dao.DaoManager; +import com.j256.ormlite.jdbc.JdbcConnectionSource; +import com.j256.ormlite.stmt.QueryBuilder; +import com.j256.ormlite.stmt.SelectArg; +import com.j256.ormlite.support.ConnectionSource; +import com.j256.ormlite.support.DatabaseConnection; +import com.j256.ormlite.table.TableUtils; +import java.io.File; +import java.sql.SQLException; +import java.util.List; +import java.util.concurrent.Callable; +import mage.cards.repository.RepositoryUtil; +import org.apache.log4j.Logger; +import org.apache.shiro.crypto.RandomNumberGenerator; +import org.apache.shiro.crypto.SecureRandomNumberGenerator; +import org.apache.shiro.crypto.hash.Hash; +import org.apache.shiro.crypto.hash.Sha256Hash; +import org.apache.shiro.crypto.hash.SimpleHash; + +public enum AuthorizedUserRepository { + + instance; + + private static final String JDBC_URL = "jdbc:h2:file:./db/authorized_user.h2;AUTO_SERVER=TRUE"; + private static final String VERSION_ENTITY_NAME = "authorized_user"; + // raise this if db structure was changed + private static final long DB_VERSION = 0; + private static final RandomNumberGenerator rng = new SecureRandomNumberGenerator(); + + private Dao dao; + + private AuthorizedUserRepository() { + File file = new File("db"); + if (!file.exists()) { + file.mkdirs(); + } + try { + ConnectionSource connectionSource = new JdbcConnectionSource(JDBC_URL); + boolean obsolete = RepositoryUtil.isDatabaseObsolete(connectionSource, VERSION_ENTITY_NAME, DB_VERSION); + + if (obsolete) { + TableUtils.dropTable(connectionSource, AuthorizedUser.class, true); + } + + TableUtils.createTableIfNotExists(connectionSource, AuthorizedUser.class); + dao = DaoManager.createDao(connectionSource, AuthorizedUser.class); + } catch (SQLException ex) { + Logger.getLogger(AuthorizedUserRepository.class).error("Error creating authorized_user repository - ", ex); + } + } + + public void add(final String userName, final String password) { + try { + dao.callBatchTasks(new Callable() { + @Override + public Object call() throws Exception { + try { + Hash hash = new SimpleHash(Sha256Hash.ALGORITHM_NAME, password, rng.nextBytes(), 1024); + AuthorizedUser user = new AuthorizedUser(userName, hash); + dao.create(user); + } catch (SQLException ex) { + Logger.getLogger(AuthorizedUserRepository.class).error("Error adding a user to DB - ", ex); + } + return null; + } + }); + } catch (Exception ex) { + } + } + + public AuthorizedUser get(String userName) { + try { + QueryBuilder qb = dao.queryBuilder(); + qb.where().eq("name", new SelectArg(userName)); + List results = dao.query(qb.prepare()); + if (results.size() == 1) { + return results.get(0); + } + return null; + } catch (SQLException ex) { + } + return null; + } + + public void closeDB() { + try { + if (dao != null && dao.getConnectionSource() != null) { + DatabaseConnection conn = dao.getConnectionSource().getReadWriteConnection(); + conn.executeStatement("shutdown compact", 0); + } + } catch (SQLException ex) { + } + } +} diff --git a/Mage.Server/src/main/java/mage/server/Session.java b/Mage.Server/src/main/java/mage/server/Session.java index 9e49fcd24b..2daabc14a8 100644 --- a/Mage.Server/src/main/java/mage/server/Session.java +++ b/Mage.Server/src/main/java/mage/server/Session.java @@ -102,6 +102,17 @@ public class Session { if (m.find()) { return "User name '" + userName + "' includes not allowed characters: use a-z, A-Z and 0-9"; } + + AuthorizedUser authorizedUser = AuthorizedUserRepository.instance.get(userName); + if (authorizedUser == null) { + // Do this in an explicit sign-up flow. + AuthorizedUserRepository.instance.add(userName, password); + } else { + if (!authorizedUser.doCredentialsMatch(userName, password)) { + return "Wrong username or password"; + } + } + // TODO: Do an authentication with userName and password. User user = UserManager.getInstance().createUser(userName, host); boolean reconnect = false;