Commit 328c24f5 by Sergey Sychugin

fix lowercase login

parents
/masterdata/ejb/target/
/masterdata/api/target/
/masterdata/persistence/target/
/masterdata/war/target/
/masterdata/ear/target/
/masterdata/service/target/
/masterdata/ejb/target/
/masterdata/nb-configuration.xml
**/.DS_Store
**/.idea
**/*.iml
**/.~*#
/masterdata/common/target/
/masterdata/target/
/masterdata/ejb/nbproject/
/masterdata/mcx-api/target/
/masterdata/mcx-persistence/target/
/masterdata/mdcrypto/target/
/masterdata/pivot/target/
/masterdata/cryptprotect/target/
user-storage-jpa: User Storage Provider with EJB and JPA
========================================================
Level: Beginner
Technologies: JavaEE, EJB, JPA
Summary: User Storage Provider with EJB and JPA
Target Product: <span>Keycloak</span>
Source: <https://github.com/keycloak/keycloak-quickstarts>
What is it?
-----------
This is an example of the User Storage SPI implemented using EJB and JPA. It shows you how you might use these components
to integrate <span>Keycloak</span> with an existing external custom user database. The example integrates with a simple relational
database schema that has one user table that stores a username, email, phone number, and password for one particular user.
Using the User Storage SPI this table is mapped to the <span>Keycloak</span> user metamodel so that it can be consumed by the <span>Keycloak</span>
runtime. Before using this example, you should probably read the User Storage SPI chapter of our server developer guide.
System Requirements
-------------------
You need to have <span>Keycloak</span> running.
All you need to build this project is Java 8.0 (Java SDK 1.8) or later and Maven 3.3.3 or later.
Build and Deploy the Quickstart
-------------------------------
You must first deploy the datasource it uses.
Start up the <span>Keycloak</span> server. Then in the directory of this example type the following maven command:
````
mvn -Padd-datasource install
````
**Note**: If the server runs on different port than `10090`, you have to specify it by setting a
maven property `keycloak.management.port`.
````
mvn -Padd-datasource install -Dkeycloak.management.port=9990
````
You only need to execute this maven command once. If you execute this again, then you will get an error message that the datasource
already exists.
If you open the pom.xml file you'll see that the add-datasource profile creates an XA datasource using the built
in H2 database that comes with the server. An XA datasource is required because you cannot use two non-xa datasources
in the same transaction. The <span>Keycloak</span> database is non-xa.
Another thing to note is that the xa-datasource created is in-memory only. If you reboot the server, any users you've
added or changes you've made to users loaded by this provider will be wiped clean.
To deploy the provider, run the following maven command:
````
mvn clean install wildfly:deploy
````
If you want to play with and modify the example, simply rerun the maven deploy command above and the new version will be hot deployed.
Enable the Provider for a Realm
-------------------------------
Login to the <span>Keycloak</span> Admin Console and got to the User Federation tab. You should now see your deployed provider in the add-provider list box.
Add the provider, save it. This will now enable the provider for the 'master' realm. Because this provider implements the UserRegistrationProvider interface, any new user you create in the
admin console or on the registration pages of <span>Keycloak</span>, will be created in the custom store used by the provider. If you go
to the Users tab in the Admin Console and create a new user, you'll be able to see the provider in action.
Integration test of the Quickstart
----------------------------------
1. Make sure you have an Keycloak server running with an admin user in the `master` realm or use the provided docker image.
2. You need to have Chrome browser installed and updated to the latest version.
3. Run `mvn test -Pkeycloak-remote`. (The datasource will be deployed automatically.)
More Information
----------------
The User Storage SPI and how you can use Java EE to implement it is covered in detail in our server developer guide.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-user-storage-jpa</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<groupId>ru.sbsoft</groupId>
<version>1.0.3</version>
<packaging>jar</packaging>
<name>Keycloak: user-storage-jpa</name>
<description>User Storage Provider with EJB and JPA</description>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>19.0.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi</artifactId>
<version>19.0.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-legacy</artifactId>
<version>19.0.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>3.3.3.Final</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
package ru.masterdata.model;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;
import org.keycloak.storage.ReadOnlyException;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
public class MdmRoleModel implements RoleModel
{
private final RoleContainerModel container;
private final String name;
public String getId() {
return this.getName();
}
public String getName() {
return this.name;
}
public void setName(final String name) {
throw new ReadOnlyException("Role is read only for this update");
}
public String getDescription() {
return null;
}
public void setDescription(final String description) {
throw new ReadOnlyException("Role is read only for this update");
}
public boolean isComposite() {
return false;
}
public void addCompositeRole(final RoleModel role) {
throw new ReadOnlyException("Role is read only for this update");
}
public void removeCompositeRole(final RoleModel role) {
throw new ReadOnlyException("Role is read only for this update");
}
public Stream<RoleModel> getCompositesStream() {
return Stream.empty();
}
public Stream<RoleModel> getCompositesStream(final String s, final Integer integer, final Integer integer1) {
return null;
}
public boolean isClientRole() {
return false;
}
public String getContainerId() {
return this.container.getId();
}
public RoleContainerModel getContainer() {
return this.container;
}
public boolean hasRole(final RoleModel role) {
return false;
}
public Map<String, List<String>> getAttributes() {
return Collections.emptyMap();
}
public void setSingleAttribute(final String name, final String value) {
throw new ReadOnlyException("Role is read only for this update");
}
public void setAttribute(final String name, final List<String> values) {
throw new ReadOnlyException("Role is read only for this update");
}
public void removeAttribute(final String name) {
throw new ReadOnlyException("Role is read only for this update");
}
public Stream<String> getAttributeStream(final String name) {
return Stream.empty();
}
public MdmRoleModel(final RoleContainerModel container, final String name) {
this.container = container;
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MdmRoleModel that = (MdmRoleModel) o;
return Objects.equals(container, that.container) && Objects.equals(name, that.name);
}
protected boolean canEqual(final Object other) {
return other instanceof MdmRoleModel;
}
@Override
public int hashCode() {
final int PRIME = 59;
int result = 1;
final Object container = this.getContainer();
result = result * 59 + ((container == null) ? 43 : container.hashCode());
final Object name = this.getName();
result = result * 59 + ((name == null) ? 43 : name.hashCode());
return result;
}
@Override
public String toString() {
return "MdmRoleModel(container=" + this.getContainer() + ", name=" + this.getName() + ")";
}
}
\ No newline at end of file
package ru.masterdata.model;
import java.util.Objects;
public class MdmUserModel
{
private String login;
private String email;
private String passwd;
private String phone;
public MdmUserModel(final String login, final String email, final String passwd, final String phone) {
this.login = login;
this.email = email;
this.passwd = passwd;
this.phone = phone;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MdmUserModel that = (MdmUserModel) o;
return login.equals(that.login) && Objects.equals(email, that.email) && Objects.equals(passwd, that.passwd) && Objects.equals(phone, that.phone);
}
@Override
public int hashCode() {
return Objects.hash(login, email, passwd, phone);
}
@Override
public String toString() {
return "MdmUserModel(login=" + this.getLogin() + ", email=" + this.getEmail() + ", passwd=" + this.getPasswd() + ", phone=" + this.getPhone() + ")";
}
public String getLogin() {
return this.login;
}
public String getEmail() {
return this.email;
}
public String getPasswd() {
return this.passwd;
}
public String getPhone() {
return this.phone;
}
}
\ No newline at end of file
package ru.masterdata.model;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.*;
import org.keycloak.storage.ReadOnlyException;
import org.keycloak.storage.StorageId;
import org.keycloak.storage.adapter.AbstractUserAdapterFederatedStorage;
import ru.masterdata.utils.DataSourceProvider;
import java.util.List;
import java.util.Set;
public class UserAdapter extends AbstractUserAdapterFederatedStorage
{
private final MdmUserModel userModel;
private final String keycloakId;
private final DataSourceProvider dataSourceProvider;
private final RealmModel realm;
public UserAdapter(final KeycloakSession session, final RealmModel realm, final ComponentModel model, final MdmUserModel userModel, final DataSourceProvider dataSourceProvider) {
super(session, realm, model);
this.userModel = userModel;
this.keycloakId = StorageId.keycloakId(model, userModel.getLogin().toLowerCase());
this.dataSourceProvider = dataSourceProvider;
this.realm = realm;
}
public Set<RoleModel> getClientRoleMappings(final ClientModel app) {
return this.getRoleMappings();
}
public Set<RoleModel> getRoleMappings() {
return this.dataSourceProvider.getUserRoles(this.userModel.getLogin(), (RoleContainerModel)this.realm);
}
public String getPassword() {
return this.userModel.getPasswd();
}
public String getUsername() {
return this.userModel.getLogin();
}
public void setUsername(final String username) {
throw new ReadOnlyException("Role is read only for this update");
}
public void setEmail(final String email) {
throw new ReadOnlyException("Role is read only for this update");
}
public String getEmail() {
return this.userModel.getEmail();
}
public String getId() {
return this.keycloakId;
}
public void setSingleAttribute(final String name, final String value) {
throw new ReadOnlyException("Role is read only for this update");
}
public void removeAttribute(final String name) {
throw new ReadOnlyException("Role is read only for this update");
}
public void setAttribute(final String name, final List<String> values) {
throw new ReadOnlyException("Role is read only for this update");
}
}
\ No newline at end of file
package ru.masterdata.storage.user;
import org.keycloak.models.*;
import ru.masterdata.utils.MD5Utils;
import org.keycloak.credential.CredentialInput;
import java.util.Collections;
import java.util.Map;
import java.util.ArrayList;
import java.util.List;
import org.keycloak.models.cache.CachedUserModel;
import ru.masterdata.model.MdmUserModel;
import ru.masterdata.model.UserAdapter;
import org.keycloak.storage.StorageId;
import ru.masterdata.utils.DataSourceProvider;
import org.keycloak.component.ComponentModel;
import org.jboss.logging.Logger;
import org.keycloak.models.cache.OnUserCache;
import org.keycloak.credential.CredentialInputValidator;
import org.keycloak.storage.user.UserQueryProvider;
import org.keycloak.storage.user.UserLookupProvider;
import org.keycloak.storage.UserStorageProvider;
public class MdmUserStorageProvider implements UserStorageProvider, UserLookupProvider, UserQueryProvider, CredentialInputValidator, OnUserCache {
private static final Logger logger = Logger.getLogger(MdmUserStorageProvider.class);
public static final String PASSWORD_CACHE_KEY = UserAdapter.class.getName() + ".password";
private final ComponentModel model;
private final KeycloakSession session;
private final DataSourceProvider dataSourceProvider;
public MdmUserStorageProvider(final ComponentModel model, final KeycloakSession session, final DataSourceProvider dataSourceProvider) {
this.model = model;
this.session = session;
this.dataSourceProvider = dataSourceProvider;
}
@Override
public void preRemove(final RealmModel realm) {
}
@Override
public void preRemove(final RealmModel realm, final GroupModel group) {
}
@Override
public void preRemove(final RealmModel realm, final RoleModel role) {
}
@Override
public UserModel getUserById(final String id, final RealmModel realm) {
MdmUserStorageProvider.logger.info("getUserById: " + id);
final String sid = StorageId.externalId(id);
final MdmUserModel user = this.dataSourceProvider.getUserByLogin(sid);
if (user == null) {
MdmUserStorageProvider.logger.info("could not find user by id: " + id);
return null;
}
return new UserAdapter(this.session, realm, this.model, user, this.dataSourceProvider);
}
public UserModel getUserByUsername(final String username, final RealmModel realm) {
MdmUserStorageProvider.logger.info("getUserByUsername: " + username);
final MdmUserModel user = this.dataSourceProvider.getUserByLogin(username);
if (user == null) {
MdmUserStorageProvider.logger.info("could not find username: " + username);
return null;
}
return new UserAdapter(this.session, realm, this.model, user, this.dataSourceProvider);
}
@Override
public UserModel getUserByEmail(final String email, final RealmModel realm) {
final MdmUserModel user = this.dataSourceProvider.getUserByEmail(email);
if (user == null) {
return null;
}
return new UserAdapter(this.session, realm, this.model, user, this.dataSourceProvider);
}
// @Override
// public void onCache(final RealmModel realm, final CachedUserModel user, final UserModel delegate) {
// final String password = ((UserAdapter) delegate).getPassword();
// if (password != null) {
// user.getCachedWith().put(MdmUserStorageProvider.PASSWORD_CACHE_KEY, password);
// }
// }
@Override
public void onCache(RealmModel realm, CachedUserModel user, UserModel delegate) {
String password = ((UserAdapter) delegate).getPassword();
if (password != null) {
user.getCachedWith().put(PASSWORD_CACHE_KEY, password);
}
}
@Override
public int getUsersCount(final RealmModel realm) {
return this.dataSourceProvider.getUserCount();
}
@Override
public List<UserModel> getUsers(final RealmModel realm) {
return this.toUserModel(dataSourceProvider.getAllUsers(), realm);
}
private List<UserModel> toUserModel(final List<MdmUserModel> users, final RealmModel realm) {
final List<UserModel> res = new ArrayList<UserModel>();
for (final MdmUserModel user : users) {
res.add(new UserAdapter(session, realm, model, user, dataSourceProvider));
}
return res;
}
public List<UserModel> getUsers(final RealmModel realm, final int firstResult, final int maxResults) {
final List<MdmUserModel> users = dataSourceProvider.getAllUsers(firstResult, maxResults);
return this.toUserModel(users, realm);
}
public List<UserModel> searchForUser(final String search, final RealmModel realm) {
return this.searchForUser(search, realm, -1, -1);
}
public List<UserModel> searchForUser(final String search, final RealmModel realm, final int firstResult, final int maxResults) {
final List<MdmUserModel> results = dataSourceProvider.searchUserByLoginOrEmail(search, firstResult, maxResults);
return this.toUserModel(results, realm);
}
public List<UserModel> searchForUser(final Map<String, String> params, final RealmModel realm) {
return Collections.emptyList();
}
public List<UserModel> searchForUser(final Map<String, String> params, final RealmModel realm, final int firstResult, final int maxResults) {
return Collections.emptyList();
}
public List<UserModel> getGroupMembers(final RealmModel realm, final GroupModel group, final int firstResult, final int maxResults) {
return Collections.emptyList();
}
public List<UserModel> getGroupMembers(final RealmModel realm, final GroupModel group) {
return Collections.emptyList();
}
@Override
public List<UserModel> getRoleMembers(final RealmModel realm, final RoleModel role, final int firstResult, final int maxResults) {
return Collections.emptyList();
}
@Override
public List<UserModel> getRoleMembers(final RealmModel realm, final RoleModel role) {
return Collections.emptyList();
}
@Override
public List<UserModel> searchForUserByUserAttribute(final String attrName, final String attrValue, final RealmModel realm) {
return Collections.emptyList();
}
@Override
public boolean supportsCredentialType(final String credentialType) {
return "password".equals(credentialType);
}
@Override
public boolean isConfiguredFor(final RealmModel realmModel, final UserModel userModel, final String credentialType) {
return this.supportsCredentialType(credentialType);
}
public String getPassword(UserModel user) {
String password = null;
if (user instanceof CachedUserModel) {
password = (String) ((CachedUserModel) user).getCachedWith().get(PASSWORD_CACHE_KEY);
} else if (user instanceof UserAdapter) {
password = ((UserAdapter) user).getPassword();
}
return password;
}
@Override
public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) {
if (!supportsCredentialType(input.getType()) || !(input instanceof UserCredentialModel)) return false;
UserCredentialModel cred = (UserCredentialModel) input;
String password = getPassword(user);
return password != null &&
MD5Utils.getHexString(cred.getValue()).equalsIgnoreCase(password);
// password.equals(cred.getValue());
}
public boolean isValidOld(final RealmModel realmModel, final UserModel userModel, final CredentialInput credentialInput) {
if (!this.supportsCredentialType(credentialInput.getType())) {
MdmUserStorageProvider.logger.debugv("Credential type \"{0}\" is not supported", credentialInput.getType());
return false;
}
final String passwdHash = ((UserAdapter) userModel).getPassword();
final String password = credentialInput.getChallengeResponse();
if (password == null) {
MdmUserStorageProvider.logger.debugv("Credential type null is not supported");
return false;
}
return MD5Utils.getHexString(password).equalsIgnoreCase(passwdHash);
}
@Override
public void close() {
}
}
\ No newline at end of file
package ru.masterdata.storage.user;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.storage.UserStorageProviderFactory;
import ru.masterdata.utils.DataSourceProvider;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class MdmUserStorageProviderFactory implements UserStorageProviderFactory<MdmUserStorageProvider> {
private static final Logger logger = Logger.getLogger(MdmUserStorageProviderFactory.class);
private static final String MODULE_NAME = "masterdata-user-storage-jpa";
private static final String MODULE_DESC = "JPA Masterdata User Storage Provider";
private DataSourceProvider dataSourceProv;
public MdmUserStorageProviderFactory() {
}
@Override
public void init(final Config.Scope config) {
this.initDataSource("java:/jdbc/smdm");
}
private void initDataSource(final String jndiDataSourceName) {
InitialContext ctx = null;
try {
ctx = new InitialContext();
final DataSource dataSource = (DataSource) ctx.lookup(jndiDataSourceName);
this.dataSourceProv = new DataSourceProvider(dataSource);
} catch (NamingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
public MdmUserStorageProvider create(final KeycloakSession session, final ComponentModel model) {
try {
return new MdmUserStorageProvider(model, session, this.dataSourceProv);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public String getId() {
return MODULE_NAME;
}
@Override
public String getHelpText() {
return MODULE_DESC;
}
public void close() {
MdmUserStorageProviderFactory.logger.info((Object) "<<<<<< Closing factory");
}
}
\ No newline at end of file
package ru.masterdata.utils;
import ru.masterdata.model.MdmRoleModel;
import java.util.HashSet;
import org.keycloak.models.RoleModel;
import java.util.Set;
import org.keycloak.models.RoleContainerModel;
import java.util.ArrayList;
import java.util.List;
import java.sql.PreparedStatement;
import java.sql.Connection;
import java.sql.SQLException;
import ru.masterdata.model.MdmUserModel;
import java.sql.ResultSet;
import javax.sql.DataSource;
public class DataSourceProvider {
private static final int COL_LOGIN = 1;
private static final int COL_MAIL = 2;
private static final int COL_PASSWD = 3;
private static final int COL_PHONE = 4;
private final DataSource dataSource;
private static final String USER_ALL = "select login,email,passwd,phone from MDM_CL_USER ";
private static final String USER_ALL_WINDOW = "select login,email,passwd,phone from MDM_CL_USER offset ? limit ?";
private static final String USER_COUNT = "select count(*) from MDM_CL_USER ";
private static final String USER_BY_LOGIN = "select login,email,passwd,phone from MDM_CL_USER where lower(login)=?";
private static final String USER_BY_EMAIL = "select login,email,passwd,phone from MDM_CL_USER where lower(email)=?";
private static final String USER_SEARCH = "select login,email,passwd,phone from MDM_CL_USER where ( lower(login) like ? or email like ? ) order by login offset ? limit ?";
private static final String USER_ROLE = "select role_code from mdm_user_role_view where lower(login)=?";
public DataSourceProvider(final DataSource dataSource) {
this.dataSource = dataSource;
}
private MdmUserModel toModel(final ResultSet resultSet) throws SQLException {
return new MdmUserModel(resultSet.getString(COL_LOGIN), resultSet.getString(COL_MAIL), resultSet.getString(COL_PASSWD), resultSet.getString(COL_PHONE));
}
private MdmUserModel getUserFromQry(final String sql, final String login) {
try (final Connection connection = this.dataSource.getConnection();
final PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setString(COL_LOGIN, login.toLowerCase());
final ResultSet resultSet = stmt.executeQuery();
if (resultSet.next()) {
return toModel(resultSet);
}
return null;
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public MdmUserModel getUserByLogin(final String login) {
return this.getUserFromQry(USER_BY_LOGIN, login.toLowerCase());
}
public MdmUserModel getUserByEmail(final String mail) {
return this.getUserFromQry(USER_BY_EMAIL, mail);
}
public int getUserCount() {
try (final Connection connection = this.dataSource.getConnection(); final PreparedStatement stmt = connection.prepareStatement(USER_COUNT)) {
final ResultSet resultSet = stmt.executeQuery();
if (resultSet.next()) {
return resultSet.getInt(1);
}
return 0;
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public List<MdmUserModel> getAllUsers() {
try (final Connection connection = dataSource.getConnection(); final PreparedStatement stmt = connection.prepareStatement(USER_ALL)) {
final ResultSet resultSet = stmt.executeQuery();
final List<MdmUserModel> result = new ArrayList<MdmUserModel>();
while (resultSet.next()) {
result.add(this.toModel(resultSet));
}
return result;
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public List<MdmUserModel> getAllUsers(final int first, final int max) {
try (final Connection connection = this.dataSource.getConnection(); final PreparedStatement stmt = connection.prepareStatement(USER_ALL_WINDOW)) {
stmt.setInt(1, first);
stmt.setInt(2, max);
final ResultSet resultSet = stmt.executeQuery();
final List<MdmUserModel> result = new ArrayList<MdmUserModel>();
while (resultSet.next()) {
result.add(this.toModel(resultSet));
}
return result;
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public Set<RoleModel> getUserRoles(final String login, final RoleContainerModel realm) {
try (final Connection connection = this.dataSource.getConnection(); PreparedStatement stmt = connection.prepareStatement(USER_ROLE)) {
stmt.setString(COL_LOGIN, login.toLowerCase());
final ResultSet resultSet = stmt.executeQuery();
final Set<RoleModel> result = new HashSet<RoleModel>();
while (resultSet.next()) {
result.add(new MdmRoleModel(realm, resultSet.getString(COL_LOGIN)));
}
return result;
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public List<MdmUserModel> searchUserByLoginOrEmail(final String search, final int firstResult, final int maxResults) {
try (Connection connection = dataSource.getConnection(); PreparedStatement stmt = connection.prepareStatement(USER_SEARCH)) {
final String searchParam = "%" + search.toLowerCase() + "%";
stmt.setString(COL_LOGIN, searchParam);
stmt.setString(COL_MAIL, searchParam);
stmt.setInt(3, (firstResult != -1) ? firstResult : 0);
stmt.setInt(4, (maxResults != -1) ? maxResults : Integer.MAX_VALUE);
final ResultSet resultSet = stmt.executeQuery();
final List<MdmUserModel> result = new ArrayList<>();
while (resultSet.next()) {
result.add(this.toModel(resultSet));
}
return result;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
\ No newline at end of file
package ru.masterdata.utils;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.MessageDigest;
import java.nio.charset.Charset;
public class MD5Utils
{
private static final Charset UTF_8=StandardCharsets.UTF_8;
private static final String OUTPUT_FORMAT = "%-20s:%s";
private static byte[] digest(final byte[] input) {
MessageDigest md;
try {
md = MessageDigest.getInstance("MD5");
}
catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException(e);
}
return md.digest(input);
}
private static String bytesToHex(final byte[] bytes) {
final StringBuilder sb = new StringBuilder();
for (final byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
public static String getHexString(final String pText) {
return bytesToHex(digest(pText.getBytes(MD5Utils.UTF_8)));
}
public static void main(final String[] args) {
final String pText = "GPI_cur";
System.out.println(String.format(OUTPUT_FORMAT, "Input (string)", "GPI_cur"));
System.out.println(String.format(OUTPUT_FORMAT, "Input (length)", "GPI_cur".length()));
final byte[] md5InBytes = digest("GPI_cur".getBytes(MD5Utils.UTF_8));
System.out.println(String.format(OUTPUT_FORMAT, "MD5 (hex) ", bytesToHex(md5InBytes)));
System.out.println(String.format(OUTPUT_FORMAT, "MD5 (length)", md5InBytes.length));
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
<dependencies>
<module name="org.keycloak.keycloak-model-legacy" meta-inf="import"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
\ No newline at end of file
{
"realm": "quickstart",
"enabled": true,
"accessTokenLifespan": 60,
"accessCodeLifespan": 60,
"accessCodeLifespanUserAction": 300,
"ssoSessionIdleTimeout": 600,
"ssoSessionMaxLifespan": 36000,
"sslRequired": "external",
"registrationAllowed": false,
"privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
"publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
"requiredCredentials": [ "password" ],
"users" : [
{
"username" : "alice",
"enabled": true,
"email" : "alice@keycloak.org",
"firstName": "Alice",
"lastName": "Liddel",
"credentials" : [
{ "type" : "password",
"value" : "password" }
],
"realmRoles": [ "user", "offline_access" ],
"clientRoles": {
"account": [ "manage-account" ]
}
},
{
"username" : "test-admin",
"enabled": true,
"email" : "test@admin.org",
"firstName": "Admin",
"lastName": "Test",
"credentials" : [
{ "type" : "password",
"value" : "password" }
],
"realmRoles": [ "user","admin" ],
"clientRoles": {
"realm-management": [ "realm-admin" ],
"account": [ "manage-account" ]
}
}
],
"roles" : {
"realm" : [
{
"name": "user",
"description": "User privileges"
},
{
"name": "admin",
"description": "Administrator privileges"
}
]
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment