gpt4 book ai didi

java - 通过示例进行 DropWizard 身份验证

转载 作者:IT老高 更新时间:2023-10-28 20:45:38 24 4
gpt4 key购买 nike

我正在尝试了解 DropWizard 中身份验证和授权的工作原理。 .我读过他们的auth guide以及 dropwizard-security GitHub 上的项目,但感觉我仍然缺少一些重要的概念。

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);
}

我认为我已经为基本身份验证正确配置了一半,但不了解 SimpleCredentialSimplePrincipal 所扮演的角色。具体来说:

  1. 如何从 Jersey/JAX-RS 客户端设置基本身份验证用户名/密码?
  2. SimpleCredentialSimplePrincipal 在基本身份验证中扮演什么角色?我是否需要向它们或其他类添加任何内容以使基本身份验证正常工作,以便唯一有效的用户名是 simple_user 而唯一有效的密码是 12345
  3. 如何通过 SimplePrincipal 强制访问/授权/角色?还是网络服务不存在授权的概念?

最佳答案

问题一:

Basic Authentication协议(protocol)规定客户端请求应具有

形式的 header
Authorization: Basic Base64Encoded(username:password)

其中 Base64Encoded(username:password)username:password 的实际 Base64 编码字符串。例如,如果我的用户名和密码是 peeskillet:pass,则 header 应发送为

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);

这就是我们使用授权 header 发出简单 GET 请求所需的全部内容。

问题2:

SimpleCredential: 对于基本身份验证,我们实际上需要使用 BasicCredentials,而不是我们自己的凭据。基本上,请求将通过 BasicAuthProvider。提供者将解析 Authorization header 并从解析的用户名和密码创建一个 BasicCredentials 对象。一旦该处理完成,BasicCredentials 将被传递给我们的 SimpleAuthenticator。我们使用这些凭据对用户进行身份验证。

SimplePrincipal: 基本上是我们将用来授权客户端的东西。在认证过程中,我们可以构建一个主体,稍后将用于授权(参见问题 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";
}

问题3:

有些人可能更喜欢有一个额外的授权过滤层,但 Dropwizard 似乎有一种固执的观点,即授权应该发生在资源类中(我忘记了我在哪里读到的,但我相信 他们的论点是可测试性)。我们在 SimpleAuthenticator 中创建的 SimplePrincial 会发生什么,它可以通过使用 @Auth 注入(inject)到我们的资源方法中注释。我们可以使用 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"}

另外需要说明的是,Basic auth 本身并不安全,建议通过 SSL 进行


查看相关内容:


更新

几件事:

  • 对于 Dropwizard 0.8.x,Basic Auth 的配置有所改变。可以看more here .一个简单的例子是

    SimpleAuthenticator auth = new SimpleAuthenticator();
    env.jersey().register(AuthFactory.binder(
    new BasicAuthFactory<>(auth,"Example Realm",SimplePrincipal.class)));
  • AuthenticationException

  • 的推荐用法见上面的链接

关于java - 通过示例进行 DropWizard 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27392224/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com