所以,對於一些背景,原因你應該只拋出一個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
的異常。但是,正確的做法是:
- 實現新的AuthFilter篩選立足其關閉
io.dropwizard.auth.AuthFilter
- 覆蓋上
AuthFilter
在認證方法來檢查你的用戶,並拋出了正確的異常出現。
難道你不能只是創建一個標準非活動用戶,並返回這個用戶呢?或者,你可以創建一個基本的角色系統,如文檔和這裏所述:http://stackoverflow.com/questions/27392224/dropwizard-auth-by-example並創建一個「禁用」的角色,也不? – Dominik
在我看來,這兩種解決方法,謝謝你的建議。這是否意味着DW無法爲此要求提供解決方案? 正如在這兩種情況下,當用戶試圖訪問一個資源而不是'401'時,他將得到'403'。因爲他將是一個沒有權限的有效登錄用戶,事實並非如此。他應該被視爲仍然沒有登錄的用戶,他們應該總是得到'401'錯誤。 –
我相信DW不希望你拋出任何其他異常,因爲auth處理程序不處理它。你當然可以拋出你自己的異常,並有一個處理程序返回你的特定用例的正確響應。他們想要避免的是身份驗證在驗證錯誤時返回500錯誤。或者,編寫你自己的認證過濾器。 – pandaadb