DropWizard Auth通过示例
我试图了解DropWizard中身份验证和授权的工作方式。我已经阅读了他们的身份验证指南以及GitHub上的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子类中:
@Overridepublic 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发挥。特别:
- 如何从Jersey / JAX-RS客户端设置基本身份验证用户名/密码?
- 什么作用SimpleCredential,并SimplePrincipal与基本身份验证戏?我是否需要向它们或其他类添加任何内容以使基本身份验证工作,使得唯一有效的用户名是simple_user,唯一有效的密码是12345?
- 如何通过强制执行访问/授权/角色SimplePrincipal?还是Web服务不存在授权的概念?
回答:
回答:
基本身份验证协议规定客户端请求应具有以下形式的标头:
Authorization: Basic Base64Encoded(username:password)其中Base64Encoded(username:password)是的实际Base64编码的字符串username:password。例如,如果我的用户名和密码为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请求了。
回答:
对于基本身份验证,实际上将要求我们使用BasicCredentials,而不是我们自己的凭据。基本上,请求将通过BasicAuthProvider。提供者将解析Authorization标头,并BasicCredentials根据解析的用户名和密码创建一个对象。处理完成后,BasicCredentials将会传递给我们SimpleAuthenticator的。我们使用这些凭据对用户进行身份验证。
基本上就是我们用来 授权
客户端的内容。在身份验证过程中,我们可以构建一个主体,该主体将在以后用于授权(请参阅问题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的SSL
回答:
几件事:
- 对于Dropwizard 0.8.x,基本身份验证的配置有所更改。你可以 看到 。一个简单的例子是
        SimpleAuthenticator auth = new SimpleAuthenticator();    env.jersey().register(AuthFactory.binder(
            new BasicAuthFactory<>(auth,"Example Realm",SimplePrincipal.class)));
- 请参阅上面的链接以获取推荐的用法 AuthenticationException
以上是 DropWizard Auth通过示例 的全部内容, 来源链接: utcz.com/qa/410211.html





