web-dev-qa-db-fra.com

Comment contrôler l'accès et les droits dans JSF?

Je souhaite contrôler l'accès après la connexion de l'utilisateur à mon système.

Par exemple:

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

Donc, après avoir connu le droit de l'utilisateur, vérifié dans la base de données, je voudrais restreindre ce que cet utilisateur peut voir et faire. Il existe un moyen simple de le faire?

MODIFIER

@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() {
    }
}
23
Valter Silva

Eh bien, c'est un sujet assez large. Comme vous commencez avec l'authentification homebrewed, je vais cibler la réponse sur l'autorisation homebrewed.


La vérification des rôles en Java/JSF est relativement simple en soi si le modèle est judicieusement conçu. En supposant qu'un seul utilisateur peut avoir plusieurs rôles (comme c'est souvent le cas dans les applications du monde réel), vous aimeriez finalement avoir quelque chose comme:

public class User {

    private List<Role> roles;

    // ...

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

}
public enum Role {

    EMPLOYEE, MANAGER, ADMIN;

}

afin que vous puissiez le vérifier comme suit dans vos vues 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')}" />

et dans votre filtre:

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

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

La partie la plus difficile consiste à traduire ce modèle Java en un modèle de base de données sain. Il existe plusieurs façons différentes selon les besoins concrets de l'entreprise, chacune avec ses propres avantages ou inconvénients. Ou peut-être avez-vous déjà un Modèle de base de données sur lequel vous devez baser votre Java (donc, vous devez concevoir de bas en haut)?

Quoi qu'il en soit, en supposant que vous utilisez JPA 2.0 (l'historique de vos questions le confirme au moins) et que vous pouvez concevoir de haut en bas, l'un des moyens les plus simples serait de mapper la propriété roles en tant que @ElementCollection contre une table user_roles. Comme nous utilisons une énumération Role, une deuxième table role n'est pas nécessaire. Encore une fois, cela dépend des exigences fonctionnelles et commerciales concrètes.

En termes SQL génériques, la table user_roles Peut ressembler à ceci:

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

Ce qui doit ensuite être cartographié comme suit:

@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;

C'est essentiellement tout ce que vous devez changer dans votre entité User.


À côté de l'authentification homebrewed (connexion/déconnexion) et de l'autorisation (vérification des rôles), il y a aussi Java EE fourni authentification gérée par conteneur avec lequel vous pouvez connexion par j_security_check ou HttpServletRequest#login() , filtrer les requêtes HTTP par <security-constraint> dans web.xml , vérifier la utilisateur connecté par #{request.remoteUser} et ses rôles par #{request.isUserInRole('ADMIN')} , etc.

Ensuite, il existe plusieurs frameworks tiers tels que PicketLink , Spring Security , Apache Shiro , etc. Mais tout est hors de question :)

35
BalusC