Как контролировать доступ и права в JSF?

Я хотел бы контролировать доступ после входа пользователя в систему.

Например:

administrator : can add, delete and give rights to employee
employee : fill forms only
...

Итак, зная, какое право имеет пользователь, проверяя базу данных, я хотел бы ограничить то, что этот пользователь может видеть и делать. Есть простой способ сделать это?

ИЗМЕНИТЬ

@WebFilter("/integra/user/*")
public class LoginFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {    
        HttpServletRequest req = (HttpServletRequest) request;
        Authorization authorization = (Authorization) req.getSession().getAttribute("authorization");

        if (authorization != null && authorization.isLoggedIn()) {
            // User is logged in, so just continue request.
            chain.doFilter(request, response);
        } else {
            // User is not logged in, so redirect to index.
            HttpServletResponse res = (HttpServletResponse) response;
            res.sendRedirect(req.getContextPath() + "/integra/login.xhtml");
        }
    }

    // You need to override init() and destroy() as well, but they can be kept empty.


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void destroy() {
    }
}

Ответ 1

Хорошо, это довольно широкий предмет. Когда вы начнете с проверки подлинности на дому, я настрою таргетинг на ответ на авторизацию на дому.


Проверка роли в Java/JSF является относительно простой, если модель разумно разработана. Предполагая, что один пользователь может иметь несколько ролей (как это часто бывает в приложениях реального мира), вы в конечном итоге хотели бы иметь что-то вроде:

public class User {

    private List<Role> roles;

    // ...

    public boolean hasRole(Role role) {
        return roles.contains(role);
    }

}
public enum Role {

    EMPLOYEE, MANAGER, ADMIN;

}

чтобы вы могли проверить его в своих представлениях JSF следующим образом:

<h:selectManyCheckbox value="#{user.roles}" disabled="#{not user.hasRole('ADMIN')}">
    <f:selectItems value="#{Role}" />
</h:selectManyCheckbox>
<h:commandButton value="Delete" rendered="#{user.hasRole('ADMIN')}" />

и в вашем фильтре:

String path = req.getRequestURI().substring(req.getContextPath().length());

if (path.startsWith("/integra/user/admin/") && !user.hasRole(Role.ADMIN)) {
    res.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}

Самая сложная часть - перевод этой Java-модели на разумную модель БД. Существует несколько разных способов, в зависимости от конкретных бизнес-требований, каждый из которых имеет свои преимущества. Или, возможно, у вас уже есть модель БД, на которой вы должны основывать свою модель Java (таким образом, вам нужно создать снизу вверх)?

В любом случае, предполагая, что вы используете JPA 2.0 (ваша история вопроса хотя бы подтверждает это), и что вы можете проектировать сверху вниз, одним из самых простых способов было бы сопоставить свойство roles как @ElementCollection в таблице user_roles. Поскольку мы используем перечисление Role, вторая таблица Role не нужна. Опять же, это зависит от конкретных функциональных и бизнес-требований.

В общих терминах SQL таблица user_roles может выглядеть так:

CREATE TABLE user_roles (
    user_id BIGINT REFERENCES user(id),
    role VARCHAR(16) NOT NULL,
    PRIMARY KEY(user_id, role)
)

который затем должен отображаться следующим образом:

@ElementCollection(targetClass=Role.class, fetch=FetchType.EAGER)
@Enumerated(EnumType.STRING)
@CollectionTable(name="user_roles", joinColumns={@JoinColumn(name="user_id")})
@Column(name="role")
private List<Role> roles;

Это в основном все, что вам нужно изменить в вашей организации User.


Рядом с проверкой подлинности на дому (login/logout) и авторизацией (проверка роли) существует также Java EE, предоставляемая управляемая контейнером аутентификация, с которой вы может войти по j_security_check или HttpServletRequest#login(), фильтровать HTTP-запросы <security-constraint> в web.xml, проверить зарегистрированного пользователя #{request.remoteUser} и его роли #{request.isUserInRole('ADMIN')} и т.д.

Тогда есть несколько сторонних фреймворков, таких как PicketLink, Spring Безопасность, Apache Shiro и т.д. Но об этом не может быть и речи:)