通过网关从JHipster UAA微服务获取错误详细信息

时间:2018-04-24 10:44:25

标签: spring jhipster microservices

上下文:我们的应用程序使用JHipster生成的网关和UAA服务(微服务架构)。 我们在尝试失败次数过多后实施阻止用户帐户。

当被阻止的用户尝试登录时,UAA服务会返回400 Bad Request,并在error_description字段中使用自定义i18n代码,前端可以使用该代码显示正确的用户错误:

{
  "error" : "invalid_grant",
  "error_description" : "error.login.locked"
}

到目前为止一切顺利。

当登录请求通过网关时会出现问题,因为答案是:

{
  "type" : "http://www.jhipster.tech/problem/problem-with-message",
  "title" : "Internal Server Error",
  "status" : 500,
  "detail" : "400 Bad Request",
  "path" : "/auth/login",
  "message" : "error.http.500"
}

此处有 2个问题

  1. HTTP状态为500.由于密码错误导致登录失败,情况也是如此... 这是生成的网关的正常预期行为吗?

  2. 通过网关丢失了前端所需的errorerror_description字段。

  3. 有没有比编辑网关authenticate方法更好的方法,检查HttpClientErrorExceptionfor并解析OAuth2Exception以获取详细信息,引发自定义异常,然后由Exceptiontranslator为了保存所需的字段?这似乎有点多,只是为了能够保存服务发送的数据。

1 个答案:

答案 0 :(得分:0)

这是我最终使用的-可能不是适当的最佳解决方案,但它可以按我的需要工作:

OAuth2AuthenticationService中,我捕获到异常(这样它不会冒泡为500内部错误)

 public ResponseEntity<OAuth2AccessToken> authenticate(HttpServletRequest request, HttpServletResponse response,
                                                      Map<String, String> params) {
    try {
        [...]
        OAuth2AccessToken accessToken = authorizationClient.sendPasswordGrant(username, password);
        [...]
        return ResponseEntity.ok(accessToken);
    } catch (HttpClientErrorException ex) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            // Throw the original exception from auth-service to keep its message (i18n code used by the frontend in my case)
            throw mapper.readValue(ex.getResponseBodyAsString(), OAuth2Exception.class);
        } catch (IOException e) {
            // If it's not a OAuth2Exception, let the error get thrown
            throw ex;
        }
    } catch (Exception ex) {
        // If it's not a OAuth2Exception, let the error get thrown
        throw ex;
    }

AuthResource.authenticate()方法中,我捕获了这些OAuth2Exception,将它们包装在自定义的AuthenticationFailureException类中,然后让ExceptionTranslator将正确的对象返回到前端(请注意BadRequest状态和消息有效负载):

@ExceptionHandler(AuthenticationFailureException.class)
public ResponseEntity<Problem> handleBadRequestAlertException(AuthenticationFailureException ex, NativeWebRequest request) {
    Problem problem = Problem.builder()
        .withStatus(BAD_REQUEST)
        .with("message", ex.getMessage())
        .build();
    return create(ex, problem, request);
}