簡體   English   中英

jax-rs 1.1帶有安全過濾器和依賴注入,如何實現呢?

[英]jax-rs 1.1 with security filter and dependency injection, how to achieve this?

例如,我有以下JAX-RS 1.1方法接收JWT令牌 ,檢查它然后處理或拒絕如下的請求:

@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方法中看到的,我需要使用相同的代碼行: 檢查令牌將其轉換為User對象如果無效則返回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可以實現這一目標嗎?

我不知道有什么辦法可以在這里完成你想要的東西,但用一些線程本地數據實現一些東西並不會太難。 基本上,過濾器將使用用戶信息存儲ThreadLocal數據,並且服務方法將能夠獲取它。 這有點像黑客但它可以讓你做你想做的事。

但是要小心 - 線程本地數據與線程一起存在 - 盡量不要在那里存儲巨大的對象,否則如果你有大量的客戶端,你可能會遇到內存問題。

編輯

在考慮了這一點之后,為什么不使用會話呢? 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和/或Servlet規范之外的任何內容,應該與app server無關。

你可以使用過濾器和/或攔截器來達到這個目的。 這是澤西的例子。

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());
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM