2017-01-11 40 views
0

dropwizard auth模塊中,我想返回到我的rest-api的調用者,該用戶爲已鎖定在dropwizard身份驗證中返回鎖定的用戶

(憑證可能是正確的,但用戶被鎖定/禁用)

我在這裏看了:http://www.dropwizard.io/1.0.5/docs/manual/auth.html但無法找到與之相關的任何東西。

Authenticator回報可選我T對象authenticate方法,以及文檔說:

如果認證 無法檢查證書時,才應拋出的AuthenticationException(例如,您的數據庫已關閉)。

+0

難道你不能只是創建一個標準非活動用戶,並返回這個用戶呢?或者,你可以創建一個基本的角色系統,如文檔和這裏所述:http://stackoverflow.com/questions/27392224/dropwizard-auth-by-example並創建一個「禁用」的角色,也不? – Dominik

+1

在我看來,這兩種解決方法,謝謝你的建議。這是否意味着DW無法爲此要求提供解決方案? 正如在這兩種情況下,當用戶試圖訪問一個資源而不是'401'時,他將得到'403'。因爲他將是一個沒有權限的有效登錄用戶,事實並非如此。他應該被視爲仍然沒有登錄的用戶,他們應該總是得到'401'錯誤。 –

+0

我相信DW不希望你拋出任何其他異常,因爲auth處理程序不處理它。你當然可以拋出你自己的異常,並有一個處理程序返回你的特定用例的正確響應。他們想要避免的是身份驗證在驗證錯誤時返回500錯誤。或者,編寫你自己的認證過濾器。 – pandaadb

回答

0

所以,對於一些背景,原因你應該只拋出一個AuthenticationException是因爲好人在DW提供的過濾器只處理這個異常。對於所有其他例外情況,這是未定義的。

對於詳見:AuthFilter#authenticate

然而,有一個非常簡單的方法做你想要什麼。

望着DW代碼,你會得到這樣的:

@Override 
    public void filter(ContainerRequestContext requestContext) throws IOException { 
     final BasicCredentials credentials = 
       getCredentials(requestContext.getHeaders().getFirst(HttpHeaders.AUTHORIZATION)); 
     if (!authenticate(requestContext, credentials, SecurityContext.BASIC_AUTH)) { 
      throw new WebApplicationException(unauthorizedHandler.buildResponse(prefix, realm)); 
     } 
    } 

這段代碼所做的就是打電話給你Authenticator解決用戶,然後檢查是否被認證。如果不是,那麼它會調用UnauthorizedHandler來檢查它需要的響應。可悲的是,處理程序沒有得到傳入的主體,所以它只能返回一個靜態異常。

現在,如果你想手工製作這個,這將是你的切入點。他們不是簡單地使用他們提供的BasicCredentialAuthFilter,而是自己寫自己認爲適合自己的東西。

但是,從代碼片段中,我們可以看到,所有這些過濾器都會引發WebApplicationException。所以我們可以簡化它。

我們的Authenticator實現可以事先進行用戶鎖定檢查,併爲我們填充例外以繞過此行爲。通過這種方式,下游邏輯被保留(對WebapplicationException作出反應,我認爲這實際上是球衣的一個特徵)(參見:異常馬普爾斯)。

因此,考慮這個例子:

public class AuthenticatorTest extends io.dropwizard.Application<Configuration> { 
    @Override 
    public void run(Configuration configuration, Environment environment) throws Exception { 
     environment.jersey().register(new MyHelloResource()); 
     UserAuth a = new UserAuth(); 
     environment.jersey().register(new AuthDynamicFeature(new BasicCredentialAuthFilter.Builder<Principal>() 
       .setAuthenticator(a).setRealm("SUPER SECRET STUFF").buildAuthFilter())); 
    } 

    public static void main(String[] args) throws Exception { 
     new AuthenticatorTest().run("server", "/home/artur/dev/repo/sandbox/src/main/resources/config/test.yaml"); 
    } 

    @Path("test") 
    @Produces(MediaType.APPLICATION_JSON) 
    public static class MyHelloResource { 

     @GET 
     @Path("asd") 
     @PermitAll 
     public String test(String x) { 
      return "Hello"; 
     } 
    } 

    public static class UserAuth implements Authenticator<BasicCredentials, Principal> { 
     @Override 
     public Optional<Principal> authenticate(BasicCredentials credentials) throws AuthenticationException { 
      throw new WebApplicationException(Response.status(403).entity("User is blocked").build()); 
     } 
    } 

} 

此代碼只是簡單地創建,而不是認證用戶名的新異常。這導致這個捲曲:

[email protected]:/$ curl "artur:[email protected]:9085/api/test/asd" 
User is [email protected]:/$ curl "artur:[email protected]:9085/api/test/asd" -v 
* Trying 127.0.0.1... 
* Connected to localhost (127.0.0.1) port 9085 (#0) 
* Server auth using Basic with user 'artur' 
> GET /api/test/asd HTTP/1.1 
> Host: localhost:9085 
> Authorization: Basic YXJ0dXI6YXJ0dXI= 
> User-Agent: curl/7.47.0 
> Accept: */* 
> 
< HTTP/1.1 403 Forbidden 
< Date: Thu, 12 Jan 2017 14:19:27 GMT 
< Content-Type: application/json 
< Content-Length: 15 
< 
* Connection #0 to host localhost left intact 
User is blocked 

現在,這可能不是您可以做的最乾淨的解決方案。如果你需要這個很快,那麼你可以拋出Authenticator的異常。但是,正確的做法是:

  1. 實現新的AuthFilter篩選立足其關閉io.dropwizard.auth.AuthFilter
  2. 覆蓋上AuthFilter在認證方法來檢查你的用戶,並拋出了正確的異常出現。
+0

感謝這個寶貴的答案,你認爲我們應該在這種情況下返回401? –

+0

這取決於你想要做什麼。 401 - 未經授權,如果「鎖定用戶」意味着它是未經授權的,那麼在這裏大概401是正確的。 – pandaadb