意外的返回值

时间:2020-03-12 20:11:28

标签: spring spring-boot spring-security spring-security-oauth2

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

@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(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

您知道我该如何解决吗?

1 个答案:

答案 0 :(得分:1)

可能是List! 因此:

@Autowired
private PasswordEncoder passwordEncoder;

@Autowired
private OldPasswordsService oldPasswordsService;

...和

@Autowired
private UserXXXService userService;

...假设,您实际上是在尝试:

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

...这就是我probalby要做的事情:

    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();
    }        
}

(未经测试或编译)

..一个技术问题/细节仍然/隐藏:我错过了“用户”和“ old_password”的“绑定” ...那么,它应该检查一个用户还是所有用户的旧密码?


第一个听起来更公平/正确:旧密码应该是“基于用户的”:

@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之外)还需要一些“调整”,例如created时间戳! )(比“版本/年龄列”更好的选择)

 @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); 

..并在控制器/服务中使用它,例如:

... // 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