Since the introduction of the JavaEE 8 security API you have the ability to write your own identity store. This allows you to fetch users and user data from a custom location and a custom service. You asked about using a database - so here is an example using a database facade together with a custom identity store;
@ApplicationScoped
public class MyIdentityStore implements IdentityStore {
@EJB private UserFacade userFacade;
@Override
public int priority() {
return 50;
}
@Override
public Set<ValidationType> validationTypes() {
return EnumSet.of(ValidationType.PROVIDE_GROUPS, ValidationType.VALIDATE);
}
@Override
public Set<String> getCallerGroups(CredentialValidationResult validationResult) {
final String userName = validationResult.getCallerPrincipal().getName();
final User user= usersFacade.find(userName);
return user.getRoles();
}
public CredentialValidationResult validate(UsernamePasswordCredential credential) {
/* Handle validation/login of the user here */
}
}
To explain the above slightly more - the getCallerGroups()
will return the roles that the user is part of - something you can then use throughout the JavaEE security API and lockdown methods such as @RolesAllowed
. The validate()
method handles the validation of the user when a check is requested by the container. Finally, the validationTypes()
method simply specifies what this Identity store should be used for - in this case we have specified both the fetching of roles and handling of validation.
So since EE8 introduced this - it has become really flexible and easy to take advantage of the security features in the platform.
Here are some really great references on the subject;
https://www.ibm.com/developerworks/library/j-javaee8-security-api-1
https://www.ibm.com/developerworks/library/j-javaee8-security-api-2
https://www.ibm.com/developerworks/library/j-javaee8-security-api-3
https://www.baeldung.com/java-ee-8-security