2016-05-30 2 views
4

Например, у меня есть следующие JAX-RS 1.1 метод, который получает JWT token, проверить его, а затем процесс или отклонить запрос, как следующее:jax-rs 1.1 с фильтром безопасности и инъекцией зависимости, как этого достичь?

@GET 
public Response getBook(@HeaderParam("Authorization") String authorizationToken, @QueryParam("id") String bookId) { 

    //if(authorizationToken is a valid JWT token) 
    //  get User object which represented by this token 
    //  get required book from database 
    //  return 200 code with a book within response 
    //else if(authorizationToken is invalid by whatever reason it's) 
    //  return 401 code within a response 
    //else if(database error) 
    //  return 500 code within a response 

} 

Как вы можете видеть в каждом методе JAX-RS Мне нужно используйте те же строки кода: check token, преобразовать его в User объект, return 401 ошибка, если это недействительно.

На самом деле я могу оптимизировать его, извлекая его в статическом методе, который выполнит эту проверку и вернет User объект после успеха или выбросит Exception, если что-то пошло не так. Также я могу создать webfilter, который будет проверять заголовок и проверять токен до того, как он достигнет метода jax-rs и прервет его с исключением 401, если он недействителен.

Но я хотел бы достичь всего вместе. Webfilter, который будет проверять JWT фишку, и если она действует преобразовать его в User объекта и вводить его в методе JAX-RS следующим образом:

@GET 
public Response getBook(@RequestByUser User user, @QueryParam("id") String bookId) { 

    //if(get required book from database was successfull) 
    //  return 200 code with a book within response 
    //else(database error) 
    //  return 500 code within a response 
} 

Так что, если я достиг этой точки я могу быть уверен, что Пользователь и я не должен заботиться об этом. Можно ли достичь этого с помощью JAX-RS 1.1?

ответ

3

Я не знаю, как сделать то, что вы хотите здесь, но было бы не слишком сложно реализовать что-то с некоторыми thread local data. В принципе, фильтр будет хранить данные ThreadLocal с информацией Пользователя, и методы обслуживания смогут его получить. Это немного взломать, но это позволит вам делать то, что вы хотите.

Будьте осторожны, хотя - потоки локальных данных живут вместе с потоком - старайтесь не хранить там гигантский объект или вы можете столкнуться с проблемами памяти, если у вас есть тонна клиентов.

EDIT

Подумав об этом немного, почему бы не просто использовать сессию? ThreadLocal предполагает, что фильтр и служба запускаются в одном потоке. Это вероятно, быть правдой, но не гарантировано.

Так в фильтре:

JWTFilter.java

@WebFilter(urlPatterns={"/*"} 
public class JWTFilter implements Filter { 
     public void doFilter(ServletRequest request, 
          ServletResponse response, 
          FilterChain chain) throws IOException, ServletException { 
     HttpServletRequest req = (HttpServletRequest) request; 

     String jwt = req.getHeader("Authorization"); 
     User user = getUserFromJWT(jwt); // you'll have to code this 
     if(user != null) { 
      req.getSession().setAttribute("user", user); 
      chain.doFilter(request, response); 
     } 
     else { 
      HttpServletResponse resp = (HttpServletResponse)response; 
      resp.sendError(HttpServletResponse.SC_FORBIDDEN); 
     } 
    } 
} 

YourService.java

@GET 
public Response getBook(@QueryParam("id") String bookId, 
         @Context HttpServletRequest request) { 
    User user = (User)request.getSession().getAttribute("user");  
} 

Обратите внимание на "обмануть" здесь - мы подающими HttpServletRequest так что мы можем получить сеанс и, вместе с ним, пользователя. Но из-за фильтра этот метод не будет вызываться, если проверка JWT завершилась неудачно.

Этот код не использует ничего вне спецификации JAX-RS и/или сервлета и должен быть агностическим сервером приложений.

1

Вы можете использовать фильтр и/или перехватчик для этой цели. Вот пример Jersey.

public class AuthorizationRequestFilter implements ContainerRequestFilter { 

    @Override 
    public void filter(ContainerRequestContext requestContext) 
        throws IOException { 

     final SecurityContext securityContext = 
        requestContext.getSecurityContext(); 
     if (securityContext == null || 
        !securityContext.isUserInRole("privileged")) { 

       requestContext.abortWith(Response 
        .status(Response.Status.UNAUTHORIZED) 
        .entity("User cannot access the resource.") 
        .build()); 
     } 
    } 
} 
+2

я говорил, что мне нужно решение для JAX-RS 1.1, 'ContainerRequestFilter' доступно, так как только 2,0 https://jax-rs-spec.java.net/nonav/2.0-SNAPSHOT/apidocs/javax/ws /rs/container/ContainerRequestFilter.html – Anatoly

 Смежные вопросы

  • Нет связанных вопросов^_^