2016-09-14 27 views
1

我實現了一個ContainerRequestFilter進行基於JWT認證意想不到類型:JAX-RS:自定義的SecurityContext有當注入資源的方法

@Provider 
@Priority(Priorities.AUTHENTICATION) 
public class AuthenticationFilter implements ContainerRequestFilter { 

    @Override 
    public void filter(ContainerRequestContext requestContext) throws IOException { 
     AuthenticationResult authResult = ... 
     if (authResult.isSuccessful()) { 
      // Client successfully authenticated. 
      // Now update the security context to be the augmented security context that contains information read from the JWT. 
      requestContext.setSecurityContext(new JwtSecurityContect(...)); 
     } else { 
      // Client provided no or an invalid authentication token. 
      // Deny request by sending a 401 response. 
      requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build()); 
     } 
    } 
} 

正如你所看到的,我更新請求SecurityContext,設置如果驗證成功,它將成爲我自己的自定義實現(JwtSecurityContext)的一個實例。此實現添加額外的身份驗證和授權數據,我希望稍後在我的後續過濾器和我的資源方法中訪問這些數據。

我也實施了AuthorizationFilter,在AuthenticationFilter後立即調用。在這裏,我可以訪問更新的JwtSecurityContext就好了。

但是,我在嘗試將JwtSecurityContext注入資源(方法)時遇到了問題。我目前使用澤西

,和I've read the following in its documentation

SecurityContext可以直接從 ContainerRequestContext經由getSecurityContext()方法檢索。您也可以使用setSecurityContext(SecurityContext)方法,在請求上下文中用 替換請求上下文中的默認SecurityContext,替換爲 。如果您在ContainerRequestFilter中設置了 定製SecurityContext實例,則將使用此 安全上下文實例注入JAX-RS 資源類字段。通過這種方式,您可以實施自定義 認證過濾器,該認證過濾器可以將您自己的SecurityContext設置爲 。爲確保您的自定義驗證 請求過濾器的早期執行,請使用來自Priorities的 常量將過濾器優先級設置爲AUTHENTICATION。早期執行您的身份驗證 過濾器將確保所有其他過濾器,資源,資源方法 和子資源定位器將與您的定製 SecurityContext實例一起執行。

我嘗試了JwtSecurityContext注入資源的方法,像這樣:

@Path("/somepath") 
public class SomeResource { 
    @GET 
    @Produces(MediaType.APPLICATION_JSON) 
    public List<SomeItem> getItems(@Context SecurityContext securityContext) { 
     // securityContext is of type 'SecurityContextInjectee' 
    } 
} 

正如評論指出,該securityContext變量的運行時類型變得SecurityContextInjectee。從調試中,我發現這包裝了ContainerRequest,後者又包裝了我的JwtSecurityContext。但是,沒有getter,並且我不想使用反射來深入查看此對象層次結構,因此我不知道如何獲取我的JwtSecurityContext

我已經嘗試將@Context SecurityContext securityContext更改爲@Context JwtSecurityContext jwtSecurityContext,但是如果我這樣做,變量將變爲null。我也嘗試過野外注射,但這種行爲方式相同。

我正走向一條錯誤的道路嗎?我應該在我的資源方法中訪問我的自定義SecurityContext嗎?一種替代方案可能是將我的所有數據都包含在我的JwtSecurityContext中從getUserPrincipal返回的Principal實現中。我想代理(SecurityContextInjectee)會將呼叫轉移到其底層的JwtSecurityContext,因此返回我的Principal,但我不確定,最終我寧願使用我的JwtSecurityContext,而不是將這些值包裝在Principal實現中。

+0

@peeskillet有趣的是,我不知道我可以注入ContainerRequestContext。我想我將能夠調用getSecurityContext並返回我的自定義安全上下文。 –

+0

@peeskillet是的,注入ContainerRequestContext並在該實例上調用getSecurityContext確實會返回JwtSecurityContext。謝謝!如果你願意,你可以把它作爲答案發布,我會接受它。 –

回答

3

您可以注入ContainerRequestContext(如this post中所述),並從那裏獲取SecurityContext

public List<SomeItem> getItems(@Context ContainerRequestContext context) { 
    JwtSecurityContext sec = (JwtSecurityContext)context.getSecurityContext(); 
} 
+0

謝謝。順便說一句,你碰巧知道關於JPA的一兩件事嗎?我仍然在尋找這個問題的答案:http://stackoverflow.com/questions/38664913/jpa-locking-when-performing-an-indirect-insertion –

+0

我知道一些JPA,但它不是我每天使用的東西。我認爲這個問題稍微先進一點,我的知識:-( –

+0

好吧,只是認爲它會給它一個鏡頭:)。再次感謝! –