【问题标题】:How To @JsonIgnore on Specific condition or Roles of user in Springboot如何在 Spring Boot 中针对特定条件或用户角色 @JsonIgnore
【发布时间】:2020-04-25 08:51:30
【问题描述】:

您好,我是 Spring Boot 新手。我想实现以下逻辑,我该如何实现, 说我有模特

class Person {

    // Accessible by Level 3 or Few Roles
    private int id;
    private String name;
    private String address;

    // Accessible by Level 2 or Few Roles
    private String phoneNumber;

    //Accessible by Only Level 1 or Admin Roles 
    private String aadharNo;

    @JsonIgnore
    private LocalDateTime deletedAt;
}

级别是需要通过请求将哪些数据导出为 JSON 的说明符。并且角色的优先级很高,例如

phoneNumber 可以作为 JSON 导出到请求,如果它指定 JsonInclude 如果访问级别 2 和角色是特权用户,现在是一个用户 即使指定为 2 级,普通角色也无法访问。

我怎样才能做到这一点。有什么建议吗?

【问题讨论】:

  • 我不确定是否有任何使用 spring 的选项可以为您带来开箱即用的功能。但这对我来说听起来像是一个特定的业务案例,应该通过定制服务或适合您特定需求的类似服务来处理。
  • 我认为默认的Spring没有办法存在,我需要找出正确的方法,我该怎么做。

标签: java spring-boot spring-mvc jackson-databind


【解决方案1】:

您可以使用@JsonView@RestControllerAdvice 来做到这一点.....

class View {
    public static class Level3 {} 
    public static class Level2 extends Level3 {}
    public static class Level1 extends Level2 {}
}

class Person {

    @JsonView(View.Level3.class)
    private int id;
    private String name;
    private String address;

    @JsonView(View.Level2.class)
    private String phoneNumber;

    @JsonView(View.Level1.class) 
    private String aadharNo;

    @JsonIgnore
    private LocalDateTime deletedAt;
}

并添加此配置以检查 spring-security 授权...

@RestControllerAdvice
class SecurityJsonViewControllerAdvice extends AbstractMappingJacksonResponseBodyAdvice {

    @Override
    protected void beforeBodyWriteInternal(
      MappingJacksonValue bodyContainer,
      MediaType contentType,
      MethodParameter returnType,
      ServerHttpRequest request,
      ServerHttpResponse response) {
        if (SecurityContextHolder.getContext().getAuthentication() != null
          && SecurityContextHolder.getContext().getAuthentication().getAuthorities() != null) {
            Collection<? extends GrantedAuthority> authorities
              = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
            List<Class> jsonViews = authorities.stream()
              .map(GrantedAuthority::getAuthority)
              .map(AppConfig.Role::valueOf)
              .map(View.MAPPING::get)
              .collect(Collectors.toList());
            if (jsonViews.size() == 1) {
                bodyContainer.setSerializationView(jsonViews.get(0));
                return;
            }
            throw new IllegalArgumentException("Ambiguous @JsonView declaration for roles "
              + authorities.stream()
              .map(GrantedAuthority::getAuthority).collect(Collectors.joining(",")));
        }
    }
}

【讨论】:

  • 值得添加一个使用 writer/reader 的示例,其视图如下:String result = json.writerWithView(View.Level3.class).writeValueAsString(person);
  • @Golam 我不明白你在 RestControllerAdvice 中做了什么。你能解释一下吗。我在哪里指定级别?级别不是我的角色,所以我必须在某个地方设置用户或请求具有级别 1、2、3 访问权限。
  • 在这种情况下。是否需要已经实现控制器方法?
  • 我们可以编写任何注解或过滤器来使用n个控制器方法,这样我就不需要在每个控制器方法中编写字符串结果了吗?
  • 这里需要使用restcontrolleradvice申请spring授权
猜你喜欢
  • 1970-01-01
  • 2016-10-03
  • 2021-08-30
  • 2021-02-26
  • 2017-09-01
  • 1970-01-01
  • 2017-09-08
  • 2021-07-22
  • 1970-01-01
相关资源
最近更新 更多