- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
@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()));
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;
@Column(name = "password_owner_id", length = 4)
private Integer passwordOwnerId;
@Column(name = "created_at")
@Convert(converter = LocalDateTimeConverter.class)
private LocalDateTime createdAt;
但我得到 java.util.NoSuchElementException: No value present
。您知道我如何实现比较旧密码和新密码的逻辑吗?
编辑:我试过这个设计:
SQL查询:
public List<OldPasswords> findByOwnerId(Integer ownerId) {
String hql = "select e from " + OldPasswords.class.getName() + " e where e.passwordOwnerId = :passwordOwnerId ORDER BY e.createdAt DESC";
TypedQuery<OldPasswords> query = entityManager.createQuery(hql, OldPasswords.class).setMaxResults(3).setParameter("passwordOwnerId", ownerId);
List<OldPasswords> list = query.getResultList();
return list;
}
端点:
@PostMapping("reset_password")
public ResponseEntity<?> reset(@RequestBody PasswordResetDTO resetDTO) {
return this.userService.findByLogin(resetDTO.getName()).map(user -> {
Integer userId = user.getId();
List<OldPasswords> list = oldPasswordsService.findByOwnerId(userId);
if(!list.isEmpty() && !list.isEmpty()) {
for (int i = 0; i<list.size(); i++){
OldPasswords value = list.get(i);
boolean matches = passwordEncoder.matches(resetDTO.getPassword(), value.getEncryptedPassword());
if (matches) {
return new ResponseEntity<>("PASSWORD_ALREADY_USED", HttpStatus.BAD_REQUEST);
}
}
}
OldPasswords oldPasswords = new OldPasswords();
oldPasswords.setEncryptedPassword(passwordEncoder.encode(resetDTO.getPassword()));
oldPasswords.setPasswordOwnerId(userId);
oldPasswordsService.save(oldPasswords);
user.setEncryptedPassword(passwordEncoder.encode(resetDTO.getPassword()));
user.setResetPasswordToken(null);
userService.save(user);
return ok().build();
}).orElseGet(() -> notFound().build());
}
但是当我使用相同的密码多次更改代码时,错误 PASSWORD_ALREADY_USED
没有显示。
最佳答案
我认为你的代码有几个问题。
根据实际使用的编码算法,密码编码器有多种类型。如果“passwordEncoder”的类型是 MD5、SHA1 等,您很可能会遇到密码冲突,因为您希望密码是唯一的。
意味着如果一个用户有一个弱密码,例如“topSecret123”,而另一个用户有相同的密码“topSecret123”,你的方法
oldPasswordsService.findEncryptedPassword(...)
将返回多个条目,而不是一个。
这将导致例如 NonUniqueResultException
什么的。
将密码与用户名相关联。获取由 userId(或类似的东西)给出的用户,并使用该用户的密码进行密码检查。
使用例如 BCryptPasswordEncoder
.此类型 PasswordEncoder
负责给你的东西加盐。这样可以避免在您的数据库中出现可能的重复条目。如果仅提供“密码”,这些类型的密码编码器无法计算密码或检查密码是否匹配。由于他们对您的编码密码使用“salt”,因此这些类型的密码编码器需要(salt+hashed)密码作为输入,以检查提供的密码是否匹配。
代码
OldPasswords value = list.get();
是问题所在。 Optional<OldPasswords>
可能包含 null
值(value)。一个电话.get()
在 Optional
上将null
值将导致 java.util.NoSuchElementException: No value present
.
Optional<OldPasswords> list = oldPasswordsService.findEncryptedPassword(passwordEncoder.encode("new password entered form web reset form"));
if (!list.isPresent()) {
return new ResponseEntity<>("The old password value you've entered is incorrect", HttpStatus.UNAUTHORIZED);
}
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()));
oldPasswordsService.save(oldPasswords);
}
您也不必制作 @Id
专栏unique=true
, 也不 nullable=false
没有updateable=false
.
您发布的代码使用服务并更新域对象。并且它确实返回一个ResponseEntity
.您显然将应用程序的不同层合二为一。
您暴露了信息,即所选的(新)密码已被其他用户使用!不要那样做!加起来是因为第 1 点。我已经列出了。
问题更新后,我也想更新我的答案。由于更新问题中的代码片段无法编译,我想根据我从代码片段中了解到的内容制作一个非常简单的基本示例。
我不评论问题中显示的“重置密码”设计的概念,因为中间缺少很多代码。
包括测试在内的完整代码可以在这里找到:https://github.com/mschallar/so_oldpasswords_example
问题中请求的函数的代码是:
@PostMapping("reset_password")
public ResponseEntity<?> reset(@RequestBody PasswordResetDTO resetDTO) {
Optional<User> findByLogin = this.userService.findByLogin(resetDTO.getName());
if (!findByLogin.isPresent()) {
return ResponseEntity.notFound().build();
}
User user = findByLogin.get();
Integer userId = user.getUserId();
String encodedPassword = passwordEncoder.encode(resetDTO.getPassword());
for (OldPasswords oldPasswords : oldPasswordsService.findByOwnerId(userId)) {
if (passwordEncoder.matches(resetDTO.getPassword(), oldPasswords.getEncryptedPassword())) {
// Information: Don't do that! Don't reveal that another user already has such a password!
log.info("Password already used.");
return new ResponseEntity<>("PASSWORD_ALREADY_USED", HttpStatus.BAD_REQUEST);
}
}
OldPasswords oldPasswords = new OldPasswords();
oldPasswords.setEncryptedPassword(passwordEncoder.encode(encodedPassword));
oldPasswords.setPasswordOwnerId(userId);
oldPasswordsService.save(oldPasswords);
user.setEncryptedPassword(encodedPassword);
user.setResetPasswordToken(null);
userService.save(user);
return ResponseEntity.ok().build();
}
关于java - 如何使用 Spring "matches"方法检查旧密码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60626886/
我正在尝试为匹配中的每个匹配呈现一些 HTML,但是,我不太确定 实际上是正确的。 更具体地说,我不确定我是否可以使用 v-bind:match='match'在与循环相同的元素上 v-for='ma
它具有看似简单的代码: method match(Any:U: |) { self.Str; nqp::getlexcaller('$/') = Nil } 但是,这是它的行为: (^3).matc
如果您想检查某项是否与正则表达式匹配,如果是,请打印第一组,您就可以了.. import re match = re.match("(\d+)g", "123g") if match is not N
以下两个查询的结果有差异吗? SELECT * FROM table1, table2 WHERE ( MATCH(table1.row1) AGAINST('searchstring' IN
我正在尝试为我的日志文件创建一个语法文件。它们采用以下格式: [time] LEVEL filepath:line - message 我的语法文件如下所示: :syn region logTime
String#match 和 Regexp#match 在匹配成功时返回一个 MatchData: "".match(//) # => # //.match("") # => # //.match(:
我的代码中有这个函数: func match(match: GKMatch, player playerID: String, didChangeState state: GKPlayerConnec
我对 match 和 case 之间的区别感到困惑。在 document ,其中提到match支持通用模式匹配。 > (define (m x) (match x [(list a
我在检查特定元素中的空 HTML 内容时遇到了问题。当我使用 someElement.trim().match("") 即使 HTML 内容为空,我有时也会得到 true。我改成了 someEleme
我正在尝试使用正则表达式查找包含特定词的两个词之间的所有内容,但是这些词是重复的,所以我没有得到我想要的匹配项。 例如,我想要“你好”和“再见”之间的所有内容,以便它们之间存在“苹果”一词: hell
我目前正在构建一个 PHP 脚本,它将在需要时响应 HTTP“304 Not Modified”。 (请参阅 question #2086712 了解我目前所做的事情)。 目前我回答以下问题: If-
给定以下 XML 10 我希望能够正确识别内部 的 s : result = subject.gsub(/]*>)/, '<') 解释: ]* # any number of charact
这个问题在这里已经有了答案: How to error handle 1004 Error with WorksheetFunction.VLookup? (3 个回答) 3年前关闭。 目标:查找输入
我已经尝试了好一阵子了,但是我似乎无法弄清楚这两者之间的区别。特别是,与数据数组有关的差异: PS C:>$myarray = "a", "ab", "abc" PS C:>$myarray -mat
我正在努力研究如何构建一个宏,让我可以将模式和结果以向量的形式传递给 core.match/match 。我希望能够做到这一点: (let [x {:a 1} patterns [[{:a
这个问题在这里已经有了答案: Reference - What does this regex mean? (1 个回答) 关闭 8 年前。 如果这看起来微不足道但只是为了理解正则表达式,请原谅我:
我的 MySQL 表中有大约 20 行,其 Title 列为 Elsewhere 并具有其他不同的列参数。 我目前正在使用这样的查询,因为我的大多数搜索(通过 PHP 文件)都需要我进行猜测。所以我使
当找到匹配时,我必须从字符串中删除单词 让我们看看 我的输入字符串是 “肯诺克斯路” 比赛表演中的单词表 街道 驾驶 道路 4. 车道 输出字符串应该是: KENOX 我正在使用 vb.net 作为此
我正在搜索以下形式的字符串模式: XXXAXXX # exactly 3 Xs, followed by a non-X, followed by 3Xs 所有的 X 必须是相同的字符,并且 A 不能
好吧,我是 gulp 和 sass 的新手,我正在努力让它发挥作用。我正确安装了所有东西,但我收到了这个愚蠢的错误。有解决办法吗? PS C:\Users\Bojan Kolano\Desktop\F
我是一名优秀的程序员,十分优秀!