Ошибка в фильтре авторизации (JEE6)

#java #security #jakarta-ee #java-ee-6 #servlet-filters

#java #Безопасность #джакарта-ee #java-ee-6 #servlet-фильтры

Вопрос:

Я пишу фильтр авторизации для своего приложения 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), который содержит разрешенные страницы, а также компонент для хранения сведений о .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;
        }

    }

}
  

This is how i add the filter to the web.xml file:

 <!--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") amp;amp; 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>
  

Изменения, внесенные в компонент Access:

 @XmlElement
    private User visitor;

public User getVisitor() {
        return visitor;
    }
  

Комментарии:

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

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

Ответ №1:

Если вы ничего не видите, значит, Фильтр заблокировал запрос. Т.е. он не продолжил цепочку и не переадресовал запрос. Ваш поток кода нелогичен. Вы также должны выполнить перенаправление, когда текущий пользователь является null или когда у текущего пользователя нет ни одной из этих ролей. Вы также должны вызывать chain.doFilter() or 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() an enum , чтобы вы могли использовать switch вместо if else if else if else ... и преобразовать три дублированных блока в один вспомогательный метод.


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

Комментарии:

1. Я сделал, как вы сказали, мой getUserType возвращает перечисление, и я обрабатываю его с помощью инструкции switch. Браузеры сообщают, что происходит цикл перенаправления. Я вставил последние изменения в свой код в обновлении выше

2. Смотрите обновление ответа. Измените свой if блок. Например if (notInMainXhtml amp;amp; currentUser != null) .

3. Извините, но я не уверен, правильно ли я понял. Я удалил основное окружение if, в котором написано if (CurrentUser != null) {, теперь я не вижу белого цвета, но я получаю NPE в этой строке: switch (CurrentUser.GetType()) { Это потому, что пользователь не вошел в систему, я думаю, мне нужно, чтобы if

4. Вам нужно заменить if (currentUser != null) на if (notInMainXhtml amp;amp; currentUser != null) . notInMainXhtml Предполагается, что это условие вычисляет, true если запрошенной страницы нет main.xhtml . Например. if (!pageRequested.endsWith("/main.xhtml") amp;amp; currentUser != null) .

5. Я сделал это, если(!pageRequested.contains(«main.xhtml») amp;amp; CurrentUser != null) но я все еще получаю этот цикл перенаправления при переходе к main.xml если я пытаюсь перейти на любую другую страницу, я перенаправляюсь на main.xml итак, я снова вижу цикл перенаправления. Также я хочу упомянуть, что стартовой страницей моего проекта является index.jsp, я не знаю, влияет ли это на что-то