Назначьте роли пользователю

Вместо того, чтобы все пользователи имели право делать все, я пытаюсь добавить роли (Admin, User) в рабочий проект Java EE.

Я начал сам, изменяя таблицы, писал собственный механизм и планировал управлять этим программно с помощью @WebFilter.

Вскоре я понял, что в Java EE есть что-то вроде встроенного механизма для этой цели.

Я хотел использовать эту аннотацию фильтра ролей:

@RolesAllowed("ADMIN")
public void adminAllowedFunction(){
    //code
}

Но как назначить роль фактическому пользователю / сеансу. Кроме того, что имеется в виду под пользователем в этом контексте? Требуется запись в таблице, выполняющая какое-то соглашение, или все, что я делаю, назначает роль фактическому сеансу?

Я также читал кое-что о сопоставлении ролей пользователям Glassfish / Payara (царствам). Это правильный путь? Я не нашел ничего ясного объяснения, только о <security-role-mapping> в glassfish-web.xml, но как получить это в java-коде?

Я действительно сбит с толку механизмом Java EE. Сомневаюсь, что не понял, для чего он предназначен.

Я пробовал denny для всех ролей эту функцию:

@DenyAll
public String getUserName(){
    return (String) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("loggedUser");

}

Но я не мог получить условия, когда в этом было бы отказано.

Буду благодарен за любую полезную информацию. Также не беспокойтесь о куче примеров кода.

2
0
1 277
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как правило, вам необходимо использовать механизм аутентификации Java EE. Такой механизм аутентификации вызывается в начале запроса и взаимодействует с вызывающим абонентом для получения учетных данных. Если эти учетные данные проверены правильно, он может установить имя вызывающего абонента или участника вызывающего абонента вместе с несколькими ролями в текущем запросе.

Откуда берутся имя и роли вызывающего абонента, не имеет значения для Java EE. Ваш код может изобретать их на лету, извлекать их из хранилища в памяти, запрашивать их из БД, получать их с сервера LDAP и т. д. И т. Д.

Часто, но не обязательно, механизм аутентификации делегирует задачу проверки учетных данных специализированному компоненту, который взаимодействует с хранилищем, подобным упомянутому выше. Это называется «хранилищем идентификационных данных» (существует около 20 других терминов для обозначения того же самого, но Java EE стандартизирован для этого).

Ниже приводится пример хранилища идентификационных данных:

@ApplicationScoped
public class TestIdentityStore implements IdentityStore {

    public CredentialValidationResult validate(UsernamePasswordCredential usernamePasswordCredential) {

        if (usernamePasswordCredential.compareTo("reza", "secret1")) {
            return new CredentialValidationResult("reza", new HashSet<>(asList("foo", "bar")));
        }

        return INVALID_RESULT;
    }

}

Пользовательский механизм аутентификации выглядит так:

@ApplicationScoped
public class TestAuthenticationMechanism implements HttpAuthenticationMechanism {

    @Inject
    private IdentityStoreHandler identityStoreHandler;

    @Override
    public AuthenticationStatus validateRequest(HttpServletRequest request, HttpServletResponse response, HttpMessageContext httpMessageContext) throws AuthenticationException {

        if (notNull(request.getParameter("name"), request.getParameter("password"))) {

            // Get the (caller) name and password from the request
            // NOTE: This is for the smallest possible example only. In practice
            // putting the password in a request query parameter is highly
            // insecure
            String name = request.getParameter("name");
            Password password = new Password(request.getParameter("password"));

            // Delegate the {credentials in -> identity data out} function to
            // the Identity Store
            CredentialValidationResult result = identityStoreHandler.validate(
                new UsernamePasswordCredential(name, password));

            if (result.getStatus() == VALID) {
                // Communicate the details of the authenticated user to the
                // container. In many cases the underlying handler will just store the details 
                // and the container will actually handle the login after we return from 
                // this method.
                return httpMessageContext.notifyContainerAboutLogin(
                    result.getCallerPrincipal(), result.getCallerGroups());
            } 

            return httpMessageContext.responseUnauthorized();
        } 

        return httpMessageContext.doNothing();
    }

}

Обратите внимание, что приведенное выше предназначено только для целей ДЕМО и не является реалистичным или даже безопасным механизмом аутентификации!

См. Также: https://github.com/eclipse-ee4j/soteria/tree/master/test/app-mem/src/main/java/org/glassfish/soteria/test

Часто вы не будете писать свой собственный механизм аутентификации или даже хранилище идентификаторов, а будете повторно использовать те, которые предлагает Java EE. Например:

@CustomFormAuthenticationMechanismDefinition(
    loginToContinue = @LoginToContinue(
        loginPage="/login.jsf",
        errorPage=""
    )
)
@ApplicationScoped
public class ApplicationInit {
}

Понятие пользователя существует благодаря способности запрашивать или вводить текущего вызывающего абонента / участника-пользователя. Например, используя:

@Inject
private Principal principal;

Или используя, например, API сервлета:

HttpServletRequest#getUserPrincipal();

Это тот же «пользователь» (аутентифицированная личность), с которым также проверяются @RolesAllowed и подобные конструкции.

Сопоставление групп с ролями всегда необязательно, и по умолчанию группы совпадают с ролями. Некоторые серверы вообще не поддерживают сопоставление групп и ролей.

Другие вопросы по теме