DropWizard での認証と承認の仕組みを理解しようとしています。私はGitHubの auth guide と dropwizard-security プロジェクトを読みましたが、まだいくつかの重要な概念が欠けているように感じます。
public class SimpleCredential {
private String password;
public SimpleCredential(String password) {
super();
this.password = password;
}
}
public class SimplePrincipal {
pivate String username;
public SimplePrincipal(String username) {
super();
this.username = username;
}
}
public class SimpleAuthenticator implements Authenticator<SimpleCredential, SimplePrincipal> {
@Override
public Optional<SimplePrincipal> authenticate(SimpleCredential credential) throws AuthenticationException {
if(!"12345".equals(credential.getPassword())) {
throw new AuthenticationException("Sign in failed.");
}
Optional.fromNullable(new SimplePrincipal("simple_user"));
}
}
そして、私のApplication
サブクラスで:
@Override
public void run(BackendConfiguration configuration, Environment environment) throws Exception {
environment.jersey().register(new BasicAuthProvider<SimplePrincipal>(new SimpleAuthenticator(), "SUPER SECRET STUFF"));
}
そして、リソースメソッドで:
@GET
@Path("address/{address_id}")
@Override
public Address getAddress(@Auth @PathParam("address_id") Long id) {
addressDao.getAddressById(id);
}
私はこれを基本認証用に正しく設定したと思いますが、SimpleCredential
とSimplePrincipal
が果たす役割を理解していません。具体的には:
SimpleCredential
とSimplePrincipal
は基本認証でどのような役割を果たしますか?唯一の有効なユーザー名がsimple_user
で唯一の有効なパスワードが12345
であるように、基本認証を機能させるためにそれらまたは他のクラスに何かを追加する必要がありますか?SimplePrincipal
を介してアクセス/認証/ロールを適用するにはどうすればよいですか?または、承認の概念がWebサービスに存在しないのですか?基本認証 プロトコルは、クライアント要求に次の形式のヘッダーが必要であることを示します
_Authorization: Basic Base64Encoded(username:password)
_
ここで、Base64Encoded(username:password)
は、_username:password
_の実際のBase64エンコード文字列です。たとえば、ユーザー名とパスワードが_peeskillet:pass
_の場合、ヘッダーは次のように送信されます。
_Authorization: Basic cGVlc2tpbGxldDpwYXNz
_
とはいえ、Jersey Client(1.xと仮定)には、クライアント側のフィルターであるHTTPBasicAuthFilter
があり、これがエンコード部分を処理します。したがって、クライアント側のリクエストは次のようになります
_Client client = Client.create();
WebResource resource = client.resource(BASE_URI);
client.addFilter(new HTTPBasicAuthFilter("peeskillet", "pass"));
String response = resource.get(String.class);
_
これが、認証ヘッダーを使用した単純なGETリクエストを作成するために必要なすべてのことです。
SimpleCredential:基本認証の場合、実際には独自の資格情報の代わりにBasicCredentials
を使用する必要があります。基本的に、リクエストはBasicAuthProvider
を通過します。プロバイダーはAuthorizationヘッダーを解析し、解析されたユーザー名とパスワードからBasicCredentials
オブジェクトを作成します。その処理が完了すると、BasicCredentials
がSimpleAuthenticator
に渡されます。これらの資格情報を使用してユーザーを認証します。
SimplePrincipal:は基本的に、クライアントのauthorizeに使用するものです。認証プロセスから、プリンシパルを構築できます。プリンシパルは、後で承認するために使用されます(質問3を参照)。したがって、例は次のようになります
_import com.google.common.base.Optional;
import io.dropwizard.auth.AuthenticationException;
import io.dropwizard.auth.Authenticator;
import io.dropwizard.auth.basic.BasicCredentials;
public class SimpleAuthenticator implements Authenticator<BasicCredentials,
SimplePrincipal> {
@Override
public Optional<SimplePrincipal> authenticate(BasicCredentials credentials)
throws AuthenticationException {
// Note: this is horrible authentication. Normally we'd use some
// service to identify the password from the user name.
if (!"pass".equals(credentials.getPassword())) {
throw new AuthenticationException("Boo Hooo!");
}
// from some user service get the roles for this user
// I am explicitly setting it just for simplicity
SimplePrincipal prince = new SimplePrincipal(credentials.getUsername());
prince.getRoles().add(Roles.ADMIN);
return Optional.fromNullable(prince);
}
}
_
SimplePrincipal
クラスを少し変更して、単純なRoles
クラスを作成しました。
_public class SimplePrincipal {
private String username;
private List<String> roles = new ArrayList<>();
public SimplePrincipal(String username) {
this.username = username;
}
public List<String> getRoles() {
return roles;
}
public boolean isUserInRole(String roleToCheck) {
return roles.contains(roleToCheck);
}
public String getUsername() {
return username;
}
}
public class Roles {
public static final String USER = "USER";
public static final String ADMIN = "ADMIN";
public static final String EMPLOYEE = "EMPLOYEE";
}
_
承認のために追加のフィルターレイヤーを使用することを好む人もいますが、Dropwizardは、承認がリソースクラスで発生するという見解を持っているように見えます(私はそれをどこで読んだかを忘れましたが、私は信じています彼らの主張はテスト容易性です)。 SimplePrincial
で作成したSimpleAuthenticator
で何が起こるかは、_@Auth
_アノテーションを使用してリソースメソッドに注入できることです。 SimplePrincipal
を使用して認証できます。何かのようなもの
_import dropwizard.sample.helloworld.security.Roles;
import dropwizard.sample.helloworld.security.SimplePrincipal;
import io.dropwizard.auth.Auth;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("/simple")
public class SimpleResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getResponse(@Auth SimplePrincipal principal) {
if (!principal.isUserInRole(Roles.ADMIN)) {
throw new WebApplicationException(Response.Status.FORBIDDEN);
}
return Response.ok(
"{\"Hello\": \"" + principal.getUsername() + "\"}").build();
}
}
_
したがって、この構成ですべてをまとめます
_environment.jersey().register(new BasicAuthProvider<SimplePrincipal>(
new SimpleAuthenticator(),
"Basic Example Realm")
);
_
以前に投稿したクライアント資格情報。リクエストを行うと、返されるはずです。
_{"Hello": "peeskillet"}
_
また、基本認証だけでは安全ではなく、SSL経由で行うことをお勧めします。
関連項目を参照:
いくつかのこと:
Dropwizard 0.8.xでは、基本認証の構成が少し変更されました。 詳細はこちら をご覧ください。簡単な例は
_SimpleAuthenticator auth = new SimpleAuthenticator();
env.jersey().register(AuthFactory.binder(
new BasicAuthFactory<>(auth,"Example Realm",SimplePrincipal.class)));
_
AuthenticationException
の推奨される使用法については、上記のリンクを参照してください