java ok通过复制spring-boot生成畸形的响应体

3vpjnl9f  于 2023-04-10  发布在  Java
关注(0)|答案(2)|浏览(90)

我尝试调用一个get端点。但是它在我的响应下返回重复的对象,我不知道为什么Spring返回那些格式错误的对象

@RestController
@RequestMapping("/v0/api/user")
public class UserResource {
  private final UserApplication userApplication;
  private final UserRequestResponseAssembler requestResponseAssembler;

  public UserResource(UserApplication userApplication, UserRequestResponseAssembler userRequestResponseAssembler) {
    this.userApplication = userApplication;
    this.requestResponseAssembler = userRequestResponseAssembler;
  }

  @PostMapping
  public ResponseEntity<?> createUser(@Valid @RequestBody UserRequest userRequest) {
    UserCreationRequest userCreationRequest = this.requestResponseAssembler.toUserCreationRequest(userRequest);
    UserCreationResponse userCreationResponse = this.userApplication.createUser(userCreationRequest);
    EntityModel<?> model = this.requestResponseAssembler.toEntityModel(userCreationResponse);
    return ResponseEntity.created(model.getRequiredLink(IanaLinkRelations.SELF).toUri()).build();
  }

  @GetMapping("/{id}")
  public ResponseEntity<?> getUserById(@PathVariable("id") String userId) {
    UserResponse user = this.userApplication.findById(userId);
    EntityModel<UserResponse> entityModel = this.requestResponseAssembler.toEntityModel(user);
    return ResponseEntity.ok(entityModel);
  }

  @RequestMapping(value = "/{email}", method = RequestMethod.HEAD)
  public ResponseEntity<?> existByEmail(@PathVariable("email") String email) {
    if (userApplication.checkIfUserExistByEmail(email)) return ResponseEntity.status(HttpStatus.FOUND).build();
    return ResponseEntity.notFound().build();
  }

}

这是一个userResponse记录:

public record UserResponse(String userId,
                           String firstname, String lastname, String email, String profession) {
}

这就是User.class

@Entity
@Table(name = "users")
public class User implements Serializable {
  @Id
  @Column(name = "id", nullable = false)
  @GeneratedValue(generator = "ID_GENERATOR")
  private Long id;
  @Embedded
  private UserInformation userInformation;
  @Embedded
  private AuditInformation auditInformation;
  @Embedded
  private UserId userId;

  @Embedded
  private AuthInformation authInformation;

  User() {
  }

  public User(UserInformation userInformation, AuditInformation auditInformation, AuthInformation authInformation, UserId userId) {
    this.userInformation = userInformation;
    this.userId = userId;
    this.auditInformation = auditInformation;
    this.authInformation = authInformation;
  }

  public UserInformation getUserInformation() {
    return userInformation;
  }

  public AuthInformation getAuthInformation() {
    return authInformation;
  }

  public UserId getUserId() {
    return userId;
  }

  public Set<Role> getActiveRoles() {
    Set<Role> roles = new HashSet<>();
    roles.add(Role.DEFAULT);
    return roles;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof User user)) return false;
    return getUserId().equals(user.getUserId());
  }

  @Override
  public int hashCode() {
    return Objects.hash(getUserId());
  }

  @Override
  public String toString() {
    return "User{" +
        "id=" + id +
        ", userInformation=" + userInformation +
        ", auditInformation=" + auditInformation +
        ", userId=" + userId +
        ", authInformation=" + authInformation +
        '}';
  }
}

这是UserId.class

@Embeddable
public class UserId {
  @Column(name = "user_id", nullable = false, unique = true)
  private final String id;

  public UserId() {
    this.id = UUID.randomUUID().toString();
  }

  public UserId(String stringUserId) {
    this.id = stringUserId;
  }

  public String getId() {
    return id;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof UserId userId)) return false;
    return getId().equals(userId.getId());
  }

  @Override
  public int hashCode() {
    return Objects.hash(getId());
  }

  @Override
  public String toString() {
    return "UserId{" +
        "id='" + id + '\'' +
        '}';
  }
}

这是get端点的响应:

{
    "userId": "8db4c6ab-0872-4688-8cc2-26ea93019f78",
    "firstname": "wetryyuf",
    "lastname": "dtdddddddf",
    "email": "eleanr@waldorf.com",
    "profession": null,
    "_links": {
        "self": {
            "href": "http://localhost:8080/v0/api/user/8db4c6ab-0872-4688-8cc2-26ea93019f78"
        }
    }
}{
    "userId": "8db4c6ab-0872-4688-8cc2-26ea93019f78",
    "firstname": "wetryyuf",
    "lastname": "dtdddddddf",
    "email": "eleanr@waldorf.com",
    "profession": null,
    "_links": {
        "self": {
            "href": "http://localhost:8080/v0/api/user/8db4c6ab-0872-4688-8cc2-26ea93019f78"
        }
    }
}

我不知道为什么答案是重复的。
我使用的是Java 17的Springboot。
我尝试调用一个get端点。但是它在我的响应下返回重复的对象,我不知道为什么Spring返回那些格式错误的对象。
这个方法好像被调用了两次。
这是一个调用后发生的情况的图像。
The endpoint
The response
输出建议该方法被调用两次。
我应该说明其他端点工作正常。

dwbf0jvd

dwbf0jvd1#

1.一旦检查数据库,可能是同一个id存储了两次。
1.如果存在的话,还要检查实体类和Map。
这里方法调用了两次,所以很可能有两个记录具有相同的id。

mzmfm0qo

mzmfm0qo2#

问题出在我的CustomAuthorization筛选器中。我已经像这样重新加载了内部筛选器两次,

@Component
@WebFilter(filterName = "authorizationFilter", urlPatterns = "/*")
public class AuthorizationFilter extends OncePerRequestFilter {

  private final AuthenticationUserService authenticationUserService;
  private final AuthenticationAssertion authenticationAssertion;

  @Autowired
  public AuthorizationFilter(AuthenticationUserService authenticationUserService) {
    this.authenticationUserService = authenticationUserService;
    this.authenticationAssertion = new AuthenticationAssertion();
  }

  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    if (
        this.authenticationAssertion.isUnAuthenticateURL(request)
    ) {
      final String header = request.getHeader("Authorization");
      try {
        if (!authenticationUserService.hasBearerHeader(header)) {
          filterChain.doFilter(request, response);
          return;
        }

        final String token = this.authenticationUserService.getAccessTokenString(header);
        Token retrievedToken = this.authenticationUserService.retrievedToken(token);

        if (!this.authenticationUserService.validateToken(retrievedToken)) {
          filterChain.doFilter(request, response);
          return;
        }

        UserDetails userDetails = this.authenticationUserService.loadUserByUsername(retrievedToken.getUsername());
        this.setAuthenticationContext(userDetails, request);
        filterChain.doFilter(request, response);
      } catch (Exception exception) {
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        Map<String, String> responseBody = new HashMap<>();
        responseBody.put("error", exception.getMessage());
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        new ObjectMapper().writeValue(response.getOutputStream(), responseBody);
      }
    }
    filterChain.doFilter(request, response);
  }

  private void setAuthenticationContext(UserDetails userDetails, HttpServletRequest request) {
    UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
        userDetails,
        null,
        userDetails.getAuthorities()
    );

    authenticationToken.setDetails(
        new WebAuthenticationDetailsSource().buildDetails(request)
    );

    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
  }
}

通过在else语句中传递doFilter,现在工作得很好。

@Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    if (
        this.authenticationAssertion.isUnAuthenticateURL(request)
    ) {
      final String header = request.getHeader("Authorization");
      try {
        if (!authenticationUserService.hasBearerHeader(header)) {
          filterChain.doFilter(request, response);
          return;
        }

        final String token = this.authenticationUserService.getAccessTokenString(header);
        Token retrievedToken = this.authenticationUserService.retrievedToken(token);

        if (!this.authenticationUserService.validateToken(retrievedToken)) {
          filterChain.doFilter(request, response);
          return;
        }

        UserDetails userDetails = this.authenticationUserService.loadUserByUsername(retrievedToken.getUsername());
        this.setAuthenticationContext(userDetails, request);
        filterChain.doFilter(request, response);
      } catch (Exception exception) {
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        Map<String, String> responseBody = new HashMap<>();
        responseBody.put("error", exception.getMessage());
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        new ObjectMapper().writeValue(response.getOutputStream(), responseBody);
      }
    } else {
      filterChain.doFilter(request, response);
    }
  }

相关问题