【问题标题】:Using Dropwizard Authentication manual使用 Dropwizard 身份验证手册
【发布时间】:2017-08-20 19:33:01
【问题描述】:

我目前在我的应用程序中使用http://www.dropwizard.io/1.1.0/docs/manual/auth.html# Dropwizard-Authentication。但我喜欢“手动”进行身份验证,这意味着来自未经过身份验证的 REST 接口上的特定登录/注销 API 调用。

是否有可能将 REST 调用转发到身份验证?

@POST
@Path("login")
@Consumes(MediaType.APPLICATION_JSON)
@Timed
@UnitOfWork
public Optional<LoginResponse> login(LoginRequest request) {
    // TODO forward login request to authentication
    return null;
}

提前谢谢

【问题讨论】:

  • 我建议重新考虑您的方法。也许您正在考虑网络服务器页面流。但这是 REST API,我在任何地方都没有看到过这样的东西(“转发 REST 调用”)。您不会期望客户端不知道应该做什么,并且通常您没有 HTTP cookie 等来维持登录后和请求之间的“用户会话”。
  • 您的方法应该是使用 API 端点,该端点将返回您的服务器在成功登录时生成的一些令牌,并且在一段时间内有效。例如,请参阅 JWT:jwt.io 然后保护所有其他 API 端点以检查 HTTP 请求标头中的有效令牌。
  • 有一个第三方 dropwizard 模块正在实现上述功能。看看:github.com/dhatim/dropwizard-jwt-cookie-authentication
  • 抱歉,上述项目使用 cookie 来传递 JWT 令牌。如果浏览器 Web 应用程序是消费者,这将有所帮助。还有这个:github.com/ToastShaman/dropwizard-auth-jwt - 正如我解释的那样,它实现了 JWT 令牌:您有 API 端点,您在成功授权后获得令牌,然后使用该令牌调用其他 API 端点。
  • 听上去,你的转发是到另一个端点而不是休息。因此,只需创建一个 jersey 客户端并进行调用即可。

标签: authentication dropwizard security-context


【解决方案1】:

谢谢你帮助我。我找到了这样的解决方案:

向 REST 客户端添加身份验证器

    client = ClientBuilder.newClient();
    authenticator = new Authenticator();
    client.register(authenticator);

在登录成功时设置身份验证器

    final UserAPIResponse response = create(request, UserAPI.PATH_ATTRIBUTE_DEFINITION_LOGIN);
    if (response == null || response.isFailed()) {
        connector.setupAuthenticator(null, null);
    } else {
        connector.setupAuthenticator(request.getUsername(), request.getPassword());
    }

这里是验证器

class Authenticator implements ClientRequestFilter {

@Override
public void filter(ClientRequestContext requestContext) throws IOException {
    final MultivaluedMap<String, Object> headers = requestContext.getHeaders();
    final String basicAuthentication = getBasicAuthentication();
    if (basicAuthentication == null) return;
    headers.add("Authorization", basicAuthentication);

}

void setup(String username, String password) {
    this.user = username;
    this.password = password;
}

private String getBasicAuthentication() {
    if (user == null || password == null) return null;
    final String token = this.user + ":" + this.password;
    try {
        return "BASIC " + DatatypeConverter.printBase64Binary(token.getBytes("UTF-8"));
    } catch (final UnsupportedEncodingException ex) {
        throw new IllegalStateException("Cannot encode with UTF-8", ex);
    }
}

private String password;

private String user;

}

在服务器端我有一个身份验证器

public class UserAuthenticator implements Authenticator<BasicCredentials, User> {

UserAuthenticator(UserDAO userDAO) {
    this.userDAO = userDAO;
}

@UnitOfWork
@Override
public Optional<User> authenticate(BasicCredentials credentials) throws AuthenticationException {
    final String username = credentials.getUsername();
    final Optional<DbUser> result = userDAO.getByName(username);
    if (!result.isPresent()) return Optional.empty();

    final DbUser user = result.get();
    final String password = credentials.getPassword();
    if (!StringUtils.equals(password, user.getPassword())) return Optional.empty();

    if (!user.isOnline()) return Optional.empty();
    user.handleAction();
    userDAO.save(user);

    return Optional.of(UserMgr.convert(user));
}

private final UserDAO userDAO;

}

并让它们正常工作:

SessionDao dao = new SessionDao(hibernateBundle.getSessionFactory());
ExampleAuthenticator exampleAuthenticator = new      UnitOfWorkAwareProxyFactory(hibernateBundle)
           .create(ExampleAuthenticator.class, SessionDao.class, dao);

所以最后有一个 REST-Call 来登录用户,并由客户端自动对结果进行身份验证。

【讨论】:

    猜你喜欢
    • 2017-03-15
    • 2015-03-22
    • 2014-11-23
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多