Ошибка в фильтре авторизации (JEE6) - PullRequest
2 голосов
/ 14 апреля 2011

Я пишу фильтр авторизации для своего приложения JEE6, чтобы иметь возможность ограничивать доступ определенных пользователей к некоторым страницам.По какой-то причине браузер вообще не отображает страницы (я вижу только белый).Где-то должна быть ошибка, но я не знаю где, я новичок в безопасности JEE6 и пытаюсь реализовать свой механизм аутентификации самым простым способом.

Вот мой исходный код

Фильтр:

public class RestrictPageFilter implements Filter {

    private FilterConfig fc;
    private InputStream in;
    private Access access;

    public void init(FilterConfig filterConfig) throws ServletException {
        // The easiest way to initialize the filter
        fc = filterConfig;

        // Prepare the parsing
        try {
            in = Thread.currentThread().getContextClassLoader()
                    .getResourceAsStream("allowedpages.xml");
            Access access = (Access) JAXBContext.newInstance(Access.class)
                    .createUnmarshaller().unmarshal(in);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        HttpSession session = req.getSession(true);
        String pageRequested = req.getRequestURL().toString();

        // Get the value of the current logged user
        Role currentUser = (Role) session.getAttribute("userRole");
        if (currentUser != null) {
            if (currentUser.getType().equals("BUYER")) {
                List<String> buyerPages = access.getBuyer().getPages();
                for (String s : buyerPages) {
                    if (pageRequested.contains(s)) {
                        chain.doFilter(request, response);
                    } else {
                        resp.sendRedirect("main.xml");
                    }
                }
            } else if (currentUser.getType().equals("SELLER")) {
                List<String> buyerPages = access.getSeller().getPages();
                for (String s : buyerPages) {
                    if (pageRequested.contains(s)) {
                        chain.doFilter(request, response);
                    } else {
                        resp.sendRedirect("main.xml");
                    }
                }
            } else if (currentUser.getType().equals("ADMINISTRATOR")) {
                List<String> buyerPages = access.getAdministrator().getPages();
                for (String s : buyerPages) {
                    if (pageRequested.contains(s)) {
                        chain.doFilter(request, response);
                    } else {
                        resp.sendRedirect("main.xml");
                    }
                }
            }
        }
    }

    public void destroy() {
        // Not needed
    }
}

Для поддержки этого фильтра я использую файл .xml (находится в WEB-INF / classes), который содержит разрешенные страницы, а также bean-компонент для хранения деталей.xml как объект:

<access>
    <buyer>
        <page>buyoffer.xhtml</page>
        <page>faq.xhtml</page>
        <page>index.jsp</page>
        <page>login.xhtml</page>
        <page>main.xhtml</page>
        <page>registrationSucceded.xhtml</page>     
    </buyer>
    <seller>
        <page>sellerpanel.xhtml</page>
        <page>faq.xhtml</page>
        <page>index.jsp</page>
        <page>login.xhtml</page>
        <page>main.xhtml</page>
        <page>registrationSucceded.xhtml</page>     
    </seller>
    <administrator>
        <page>sellerpanel.xhtml</page>
        <page>faq.xhtml</page>
        <page>index.jsp</page>
        <page>login.xhtml</page>
        <page>main.xhtml</page>
        <page>registrationSucceded.xhtml</page>     
    </administrator>
</access>

-

package simplebeans;

import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Access {

    @XmlElement
    private User buyer;

    @XmlElement
    private User seller;

    @XmlElement
    private User administrator;

    public User getBuyer() {
        return buyer;
    }

    public User getSeller() {
        return seller;
    }

    public User getAdministrator() {
        return administrator;
    }

    @XmlRootElement
    public static class User {

        @XmlElement(name="page")
        private List<String> pages;

        public List<String> getPages() {
            return pages;
        }

    }

}

Вот как я добавляю фильтр в файл web.xml:

<!--Page restriction filter -->
    <filter>
        <filter-name>restrict</filter-name>
        <filter-class>filters.RestrictPageFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>restrict</filter-name>
        <url-pattern>*.xhtml</url-pattern>
    </filter-mapping>

Что делатьВы думаете, почему я вижу только белое в моем браузере?Я пытаюсь перейти с помощью URL-адреса на некоторые страницы, но вижу только белый.

Обновление Я внес несколько изменений, чтобы позволить пользователям, не вошедшим в систему, видетьнекоторые страницы, но я получаю NPE:

Изменения в методе doFilter:

public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        HttpSession session = req.getSession(true);
        String pageRequested = req.getRequestURL().toString();

        // Get the value of the current logged user
        Role currentUser = (Role) session.getAttribute("userRole");
        boolean authorized = false;

        if (!pageRequested.contains("main.xhtml") && currentUser != null) {

            switch (currentUser.getType()) {
            case BUYER:
                for (String s : access.getBuyer().getPages()) {
                    if (pageRequested.contains(s)) {
                        authorized = true;
                    }
                }
                break;
            case SELLER:
                for (String s : access.getSeller().getPages()) {
                    if (pageRequested.contains(s)) {
                        authorized = true;
                    }
                }
                break;
            case ADMINISTRATOR:
                for (String s : access.getAdministrator().getPages()) {
                    if (pageRequested.contains(s)) {
                        authorized = true;
                    }
                }
                break;
            }
        }
        else {
            for (String s : access.getVisitor().getPages()) {
                if (pageRequested.contains(s)) {
                    authorized = true;
                }
            }
        }


        if (authorized || pageRequested.contains("main.xhtml")) {
            chain.doFilter(request, response);
        } else {
            resp.sendRedirect("main.xhtml");
        }
    }

Изменения в XML-файле:

<visitor>
        <page>faq.xhtml</page>      
        <page>login.xhtml</page>
        <page>main.xhtml</page> 
        <page>registration.xhtml</page>
        <page>registrationbuyer.xhtml</page>    
        <page>registrationseller.xhtml</page>
    </visitor>

Изменения, внесенные вБин доступа:

@XmlElement
    private User visitor;

public User getVisitor() {
        return visitor;
    }

1 Ответ

3 голосов
/ 14 апреля 2011

Если вы ничего не видите, тогда Фильтр заблокировал запрос.Т.е. он не продолжил цепочку, не направил и не перенаправил запрос.Ваш поток кода нелогичен.Вы также должны выполнить перенаправление, когда текущий пользователь null или когда текущий пользователь не имеет ни одной из этих ролей.Вы также должны вызывать chain.doFilter() или response.sendRedirect() эффективно только один раз во всем коде фильтра.Прямо сейчас вы вызываете их несколько раз для каждой страницы в цикле.Эти вызовы методов магическим образом не отменяют цикл for.

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

   boolean authorized = false;

   if (currentUser != null) {
        if (currentUser.getType().equals("BUYER")) {
            for (String s : access.getBuyer().getPages()) {
                if (pageRequested.contains(s)) {
                    authorized = true;
                    break;
                }
            }
        } else if (currentUser.getType().equals("SELLER")) {
            for (String s : access.getSeller().getPages()) {
                if (pageRequested.contains(s)) {
                    authorized = true;
                    break;
                }
            }
        } else if (currentUser.getType().equals("ADMINISTRATOR")) {
            for (String s : access.getAdministrator().getPages()) {
                if (pageRequested.contains(s)) {
                    authorized = true;
                    break;
                }
            }
        }
    }

    if (authorized) {
        chain.doFilter(request, response);
    } else {
        resp.sendRedirect("main.xhtml");
    }

Я бы лично сделал CurrentUser#getType() enum, чтобы вы могли использовать switch вместо if else if else if else ... и рефакторинг трех дублированных блоков в один вспомогательный метод.


Обновление : в соответствии с проблемой цикла перенаправления, если ваш фильтр сопоставлен суниверсальный шаблон URL, такой как /* (который также охватывает main.xhtml) вместо, например, /secured/*, тогда вам нужно , а не перенаправить запрос, когда текущая запрашиваемая страница main.xhtml, но вместо этого вам нужно продолжить цепочку.Вы можете сделать это, пропустив основную проверку if, если запрашиваемая в данный момент страница равна main.xhtml.В любом случае, вы не заботитесь об авторизации для main.xhtml.

...