[英]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.