意外的 return 值

Unexpected return value

我正在尝试实施密码比较。首先我尝试了这个:

@Autowired
private PasswordEncoder passwordEncoder;

@Autowired
private OldPasswordsService oldPasswordsService;

Optional<OldPasswords> list = oldPasswordsService.findEncryptedPassword(passwordEncoder.encode("new password entered form web reset form"));
            OldPasswords value = list.get();
            boolean matches = passwordEncoder.matches("new password entered form web reset form", value.getEncryptedPassword());

            if (matches)
            {
                return new ResponseEntity<>("PASSWORD_ALREADY_USED", HttpStatus.BAD_REQUEST);
            }
            else
            {
                OldPasswords oldPasswords = new OldPasswords();
                oldPasswords.setEncryptedPassword(passwordEncoder.encode(resetDTO.getPassword()));
                oldPasswords.setCreatedAt(LocalDateTime.now());
                oldPasswordsService.save(oldPasswords);
            }

Table 旧密码:

@Table(name = "old_passwords")
public class OldPasswords implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true, updatable = false, nullable = false)
    private int id;

    @Column(name = "encrypted_password", length = 255)
    private String encryptedPassword;

我尝试实现这个:

......
return this.userService.findByLogin(resetDTO.getName()).map(user -> {
            Optional<OldPasswords> list = oldPasswordsService.findEncryptedPassword(passwordEncoder.encode(resetDTO.getPassword()));
            list.ifPresent(value -> {
                boolean matches = passwordEncoder.matches(resetDTO.getPassword(), value.getEncryptedPassword());
                if (matches) {
                    return new ResponseEntity<>("PASSWORD_ALREADY_USED", HttpStatus.BAD_REQUEST);
                }
            }).orElse(() -> {
                OldPasswords oldPasswords = new OldPasswords();
                oldPasswords.setEncryptedPassword(passwordEncoder.encode(resetDTO.getPassword()));
                oldPasswordsService.save(oldPasswords);
            });
         return ok().build();

}).orElseGet(() -> notFound().build());
}

但是我得到了这一行:

return new ResponseEntity<>("PASSWORD_ALREADY_USED", HttpStatus.BAD_REQUEST);

错误

Unexpected return value

你知道我该如何解决这个问题吗?

可能List! 因此:

@Autowired
private PasswordEncoder passwordEncoder;

@Autowired
private OldPasswordsService oldPasswordsService;

...和

@Autowired
private UserXXXService userService;

...让我们假设,您实际上正在尝试:

@RequestMapping(...)
public ResponseEntity<String> resetPassword(ResetPasswordDTO dto) {
    ...

...这就是我可能会采用的方式:

    final Optional<User> user = this.userService.findByLogin(dto.getName()); // Optional or null?, let's assume Optional
    // if user (login) exists:
    if(user.isPresent()) {
        // check old passwords, the method name/data structure lets assume it's rather List than Optional:
       java.util.List<OldPasswords> list = oldPasswordsService.findEncryptedPassword(passwordEncoder.encode(dto.getPassword()));
       if(list.isEmpty()) {// list is empty...
           // do your things..
           OldPasswords oP= new OldPasswords();
           oP.setEncryptedPassword(passwordEncoder.encode(dto.getPassword()));
           oldPasswordsService.save(oP);
           return ResonseEntity.ok().build(); // ok!
       } else {// otherwise:
           return new ResponseEntity<>("PASSWORD_ALREADY_USED", HttpStatus.BAD_REQUEST);
       }
    } else { // otherwise (user.login not exists)
        return ResponseEntity<>.notFound().build();
    }        
}

(未测试也未编译)

..一个技术 question/detail remains/hidden:我想念 "user" 和 "old_password" 的 "binding"... 所以,它应该检查旧的一个用户或所有用户的密码?


第一个听起来更多fair/correct:旧密码应该是"user based":

@Entity
// some unique constraints, when you have..., would be nice
public class OldPasswords implements Serializable { // singular is better for entity/table names!
  ....
  @ManyToOne
  @JoinColumn("user_id") // if you don't want to map the entity (for some reasons), you should still map the "id".
  private User user;

  // getter/setter ...
}

...

(影响最小,)然后你可以:

public interface OldPasswordsRepository extends Repository<OldPasswords, Integer> { // <- Integer ???
    List<OldPasswords> findByUserAndEncryptedPassword(User user, String pwd); // to use that...
}

编辑:为了匹配最后三个密码,@Peter,你的数据结构需要(除了user)一些"tweak" - 比如created 时间戳!;)(比 "version/age column")

更好的选择
 @Column(nullable = false) // final + instantiation is suited here
 final Date created = new Date(); //long, LocalDateTime, DateTime... Timestamp, java.sql.Date... and many alternatives.
 // getter

..然后你可以(在存储库中):

// untested!
List<OldPasswords> findTop3ByUserOrderByCreatedDesc(User user); 

..并在 controller/service 中使用它,例如:

... // if user is present
List<OldPasswords> list = oldPasswordsRpository.findTop3ByUserOrderByCreatedDesc(user);

for(OldPasswords opw:list) {

 // compare opw to dto.getPasword if match: return "bad request"
}
// after that (no bad request), store new (& old) password... (everywhere relevant), 
// ...and when nothing fails: 
return ResponseEntity.ok().build();

// else: user not present -> return not found