безопасность джерси и управление сессиями - PullRequest
42 голосов
/ 26 мая 2009

Есть ли способ получить управление сессиями или безопасность программно на Джерси, например управление сессиями веб-приложений? Или все транзакции, сеансы и безопасность обрабатываются контейнером, в котором развернуто приложение Джерси?

Ответы [ 7 ]

70 голосов
/ 28 мая 2009

Управление сессиями является областью контейнера, в котором развернут Джерси. В большинстве производственных случаев он будет развернут в контейнере, который выполняет управление сеансом.

Приведенный ниже код является простым примером ресурса джерси, который получает объект сеанса, сохраняет значения в сеансе и получает их при последующих вызовах.

@Path("/helloworld")
public class HelloWorld {

    @GET
    @Produces("text/plain")
    public String hello(@Context HttpServletRequest req) {

        HttpSession session= req.getSession(true);
        Object foo = session.getAttribute("foo");
        if (foo!=null) {
            System.out.println(foo.toString());
        } else {
            foo = "bar";
            session.setAttribute("foo", "bar");
        }
        return foo.toString();


    }
}
22 голосов
/ 13 октября 2011

Я думал, что сессии - это то, что мы должны никогда не использовать в RESTful приложения ...

Егор прав. Мы никогда не должны поддерживать состояние на стороне сервера а-ля обычного веб-приложения. Если вы хотите создать разрозненное SOA-ориентированное приложение, вам не нужно использовать какой-либо API / framework для веб-сервисов REST. Если вам нужно или вы хотите поддерживать глобальное состояние клиент-сервер на стороне сервера, вы неявно создаете то, что мы могли бы описать как SOA-ориентированное [веб] приложение, но используя Джерси как своего рода [веб] среду разработки. Случайно вы искажаете природу веб-службы (REST или иным образом). Вы можете сделать это так, как это было предложено в первом ответе, но вы не должны . Конечный результат - не веб-сервис, а обычное приложение, созданное с помощью инструментов веб-сервисов.

-_ о

14 голосов
/ 05 ноября 2013

Да, это возможно. Джерси документация говорит:

Информация о безопасности запроса доступна при введении JAX-RS Экземпляр SecurityContext с использованием аннотации @Context. Введенный Экземпляр контекста безопасности обеспечивает эквивалент функциональности доступно на HttpServletRequest API. Введенный контекст безопасности зависит от фактического развертывания приложения в Джерси. Например, для приложение Джерси, развернутое в контейнере сервлетов, Джерси SecurityContext будет инкапсулировать информацию из контекста безопасности извлекается из запроса сервлета. В случае заявления Джерси развернутый на сервере Grizzly, SecurityContext вернет информация, полученная из запроса Grizzly.

Пример:

@Path("basket")
public ShoppingBasketResource get(@Context SecurityContext sc) {
    if (sc.isUserInRole("PreferredCustomer") {
        return new PreferredCustomerShoppingBasketResource();
    } else {
        return new ShoppingBasketResource();
    }
}

или

@Path("resource")
@Singleton
public static class MyResource {
    // Jersey will inject proxy of Security Context
    @Context
    SecurityContext securityContext;

    @GET
    public String getUserPrincipal() {
        return securityContext.getUserPrincipal().getName();
    }
}

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

Джерси также позволяет настроить SecurityContext:

SecurityContext может быть непосредственно получен из ContainerRequestContext с помощью метода getSecurityContext (). Вы также можете заменить SecurityContext по умолчанию в контексте запроса на пользовательский один с использованием метода setSecurityContext (SecurityContext). Если вы установите пользовательский экземпляр SecurityContext в вашем ContainerRequestFilter, это Экземпляр контекста безопасности будет использоваться для внедрения в JAX-RS. поля класса ресурсов. Таким образом, вы можете реализовать пользовательские фильтр аутентификации, который может настроить ваш собственный SecurityContext, чтобы быть используемый. Чтобы обеспечить раннее выполнение вашей пользовательской аутентификации фильтр запроса, установите приоритет фильтра на AUTHENTICATION, используя константы из приоритетов. Раннее выполнение вашей аутентификации фильтр будет гарантировать, что все другие фильтры, ресурсы, методы ресурсов и подресурсные локаторы будут выполняться с вашим заказом Экземпляр SecurityContext.

См. примеры использования фильтров запросов с Джерси . И проверьте мой следующий пример:

import javax.annotation.Priority;
import javax.ws.rs.Priorities;

@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthRequestFilter implements ContainerRequestFilter {
    @Context
    HttpServletRequest webRequest;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        final HttpSession session = webRequest.getSession();

        requestContext.setSecurityContext(new SecurityContext() {
            @Override
            public Principal getUserPrincipal() {
                return new PrincipalImpl((String)session.getAttribute("USER_NAME"));
            }

            @Override
            public boolean isUserInRole(String s) {
                return false;
            }

            @Override
            public boolean isSecure() {
                return false;
            }

            @Override
            public String getAuthenticationScheme() {
                return null;
            }
        });
    }
}

Внимание! Это было введено в Джерси 2.4 . Glassfish 4.0.0 использует старый Jersey 2.0, поэтому вам придется обновить Jersey с помощью этих советов (это не доказало свою эффективность). Или лучше скачать ночной сборки Glassfish 4.0.1 . но это не совсем стабильно в данный момент. Я надеюсь, что новая версия будет выпущена в ближайшее время.

UPDATE: На данный момент (2014-02-14) ночная сборка Glassfish 4.0.1 использует Jersey 2.5.1, и отлично работает внедрение контекста.

6 голосов
/ 13 июня 2009

Ответ Джека о сессиях правильный. Они специфичны для контейнера, в котором вы выполняете, хотя спецификация Servlet, по крайней мере, обеспечивает переносимость между контейнерами JavaEE.

Что касается безопасности, по крайней мере, у вас есть возможность отделить его от вашего специального кода JAX-RS, используя JaaS (Служба аутентификации и авторизации Java) и фильтр сервлета . Фильтр может использоваться для принудительной аутентификации HTTP и, при успешной аутентификации, настроить субъект JaaS с соответствующими принципалами. Ваши ресурсы JAX-RS могут проверить соответствующие Принципы по Теме. Поскольку вы управляете всем стеком, вы должны иметь возможность полагаться на аутентифицированного пользователя в своих ресурсах (но проверьте это!), И вы можете применять авторизацию на основе текущей операции в коде ресурса.

4 голосов
/ 07 ноября 2011

Я решил эту проблему, когда клиенты добавили заголовок авторизации и протестировали его в методе REST следующим образом:

@GET
@PRODUCES(MediaType.APPLICATION_JSON)
public String returnClients(@Context HTTPServletRequest request(
    String auth = request.getHeader("Authorization");
    Account acc = null;
    if (auth!=null) {
       Account acc = Utils.LoginAccount(auth);
    }
    if (acc == null)
     // not logged in, handle it gracefully

Таким образом, есть аутентификация без запуска сеанса.

3 голосов
/ 07 мая 2010

Для обеспечения безопасности на Джерси вам следует обратиться к службе поддержки OAuth. OAuth идеально подходит, когда вы предоставляете API для вашей системы внешним пользователям. Например, как API Api

http://wikis.oracle.com/display/Jersey/OAuth

2 голосов
/ 17 сентября 2014

Вы можете использовать @path для группировки сервисов под единым пространством имен. пример .

@Path("/helloworld")
public class HelloWorld {

    @GET
    @Produces("text/plain")
    public String hello() {


        return "";


    }
}
Instead of @Path("/helloworld") use
@Path("admin/helloworld") to expose you class as rest and bind filter on "admin/"
in web.xml as below.

<servlet>
            <servlet-name>jersey-serlvet</servlet-name>
            <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
            <init-param>
                <param-name>com.sun.jersey.config.property.packages</param-name>
                <param-value>/</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>jersey-serlvet</servlet-name>
            <url-pattern>/rest/*</url-pattern>
        </servlet-mapping>
         <filter>
            <filter-name>myfilter</filter-name>
            <filter-class>com.Filterclass</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>myfilter</filter-name>
            <url-pattern>/rest/admin/*</url-pattern>
        </filter-mapping> 

    public class Filterclass implements Filter {
       public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain)
                throws IOException, ServletException {
                  try{
                       chain.doFilter(request, response);
                    }catch(Exception e){
                   e.printStackTrace();
                       }
          }
    }

Вы можете проверить свою сессию в этом классе фильтров.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...