简体   繁体   English

Spring Boot Rest Controller:返回默认的Error JSON

[英]Spring Boot Rest Controller: Return default Error JSON

Within my API I like to protect the user details endpoints, so that normal logged in users can only access their user profile. 在我的API中,我喜欢保护用户详细信息端点,以便普通登录用户只能访问其用户配置文件。 Therefor I am writing the controller: 因此我正在编写控制器:

@RequestMapping(value = URL_USER + "/{id}", method = RequestMethod.GET)
@ResponseBody
public PersistentEntityResource get(PersistentEntityResourceAssembler persistentEntityResourceAssembler, @PathVariable Long id) {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

    ApplicationUser loggedInUser = applicationUserService.findByUsername(authentication.getName());
    ApplicationUser applicationUser = applicationUserService.findById(id);

    if (applicationUser.getId().equals(loggedInUser.getId())) {
        return persistentEntityResourceAssembler.toFullResource(applicationUser);
    }

    throw new IllegalAccessException();
} 

In stead of raiseing an Exception which leads to InternalServerExcetption , I like to return the default spring boot error json, like the following: 而不是引发导致InternalServerExcetption的异常,我喜欢返回默认的spring引导错误json,如下所示:

{
    "timestamp": "2019-05-08T11:42:23.064+0000",
    "status": 403,
    "error": "Forbidden",
    "message": "Access Denied",
    "path": "/user/2"
}

I would prefere a solution, which works as well for other Erros like 404. What would be the easiest way to achieve that goal? 我会优先考虑一个解决方案,对于像404这样的其他Erros也是如此。实现这一目标的最简单方法是什么?

You can use below methods for the same 您可以使用以下方法

public class FooController{

    //...
    @ExceptionHandler({ CustomException1.class, CustomException2.class })
    public String handleException() {
        return "the intended body";
    }
}

Alternatively you can put this logic in as a Global Exceptions Handler using @ControllerAdvice 或者,您可以使用@ControllerAdvice将此逻辑作为Global Exceptions Handler

@ControllerAdvice
public class RestResponseEntityExceptionHandler
        extends ResponseEntityExceptionHandler {

    @ExceptionHandler(value
            = { IllegalArgumentException.class, IllegalStateException.class })
    protected ResponseEntity<Object> handleConflict(
            RuntimeException ex, WebRequest request) {
        String bodyOfResponse = "This should be application specific";
        return handleExceptionInternal(ex, bodyOfResponse,
                new HttpHeaders(), HttpStatus.CONFLICT, request);
    }
}

After some research I found a solution which looks quite elegant: 经过一番研究后,我找到了一个看起来非常优雅的解

RestController Method looks like that: RestController方法如下所示:

@RequestMapping(value = URL_USER + "/{id}", method = RequestMethod.GET)
@ResponseBody
public PersistentEntityResource get(PersistentEntityResourceAssembler persistentEntityResourceAssembler, @PathVariable Long id) {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

    ApplicationUser loggedInUser = applicationUserService.findByUsername(authentication.getName());
    ApplicationUser applicationUser = applicationUserService.findById(id);

    if (applicationUser.getId().equals(loggedInUser.getId())) {
        return persistentEntityResourceAssembler.toFullResource(applicationUser);
    }

    throw new ForbiddenRequestException("Access not allowed");
}

Addionally I have implemented the class ForbiddenRequestException : 另外我已经实现了类ForbiddenRequestException

@ResponseStatus(value = HttpStatus.FORBIDDEN)
public class ForbiddenRequestException extends RuntimeException {
    public ForbiddenRequestException(String message) {
        super(message);
    }
}

And at least to remove the trace from the JSON by setting server.error.include-stacktrace=never in the properties, this might not be ideal, but I think in production you should do this anyway. 至少要通过在属性中设置server.error.include-stacktrace=never来从JSON中删除trace ,这可能不太理想,但我认为在生产中你应该这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM