Java 恢复密码的临时字段

Java 恢复密码的临时字段,java,spring,date,Java,Spring,Date,当我恢复密码时,会在我的项目中生成一个密码,您可以使用该密码登录到您的帐户并更改密码,我不知道如何按时间限制临时密码字段?假设用户可以使用此密码登录一个小时,我有一个日期字段作为密码,但我不知道要与它进行比较 public class SecurityUser implements UserDetails { private Integer id; private String username; private String password; private

当我恢复密码时,会在我的项目中生成一个密码,您可以使用该密码登录到您的帐户并更改密码,我不知道如何按时间限制临时密码字段?假设用户可以使用此密码登录一个小时,我有一个日期字段作为密码,但我不知道要与它进行比较

public class SecurityUser implements UserDetails {

    private Integer id;
    private String username;
    private String password;
    private String email;
    private Date lastPasswordReset;
    private Collection<? extends GrantedAuthority> authorities;
    private Boolean accountNonExpired = true;
    private Boolean accountNonLocked = true;
    private Boolean credentialsNonExpired = true;
    private Boolean enabled = true;
    private String temporaryPassword;
    private Date validatyTime;
public类SecurityUser实现UserDetails{
私有整数id;
私有字符串用户名;
私有字符串密码;
私人字符串电子邮件;
私人日期lastPasswordReset;

private Collection您可以使用ScheduledTasks重置所有已过期的临时密码,并设置指示临时密码不再有效的标志

tl;dr 过期,不是有效期 跟踪密码过期的时刻。因此将
validityTime
变量的名称更改为类似于
whentemporationpasswordexpires

当用户尝试另一次登录时,您将捕获当前时刻,然后与存储的
whenTemporaryPasswordExpires
进行比较

java.time 永远不要使用
java.util.Date
。这是java最早版本中最糟糕的日期时间类之一。这些遗留类在几年前被采用JSR 310的java.time类完全取代

设定到期日 两个阶段中的第一个阶段是在生成临时密码时设置过期时间

捕捉当前时刻

Instant instant = Instant.now() ;  // Capture the current moment in UTC.
确定临时密码有效期的业务策略。使用
持续时间
以天(24小时的时间段,而不是日历天)、小时、分钟和秒为单位跟踪时间跨度

Duration d = Duration.ofHours( 1 ) ;  // Policy says temporary password is good for one hour.
做一些日期-时间数学,将时间跨度(
Duration
对象)添加到
Instant
中,以获得表示未来时刻的新
Instant
。请注意java.time是如何使用的,因此新的
Instant
对象是基于原始值生成的

Instant expires = instant.plus( d ) ; // Date-time math, adding the one hour to the current moment gets us a moment 1 hour in the future.
将过期时间作为成员变量存储在类中

public class SecurityUser implements UserDetails {

    private Integer id;
    private String username;
    …
    private Instant whenTemporaryPasswordExpires;
    …
}
将未来时刻指定给变量

user.whenTemporaryPasswordExpires = expires ;
将当前时刻与过期时间进行比较 第二阶段,当用户尝试登录时,我们查看当前时刻是否晚于过期时间。
Instant
类具有比较方法,例如
isBefore
isAfter

boolean expired = Instant.now().isAfter( user.whenTemporaryPasswordExpires ) ;
if( expired ) {
    // TODO: Display error message about temp pw expired. Offer new temp pw.
} else {  // Else, not expired. Accept temporary password.
    // TODO: Check submitted password to see if it matches temporary password issued earlier.
}
请注意,上面的所有代码都使用了。对于过期逻辑,不需要考虑时区。如果要显示过期,请搜索堆栈溢出以了解
ZoneId
ZonedDateTime
、以及
DateTimeFormatter.ofLocalized…


在上面的讨论中,我忽略了一个明显的问题,即我们从不存储密码。我们使用satting和hash,但这是一个完全不同的讨论


关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,如,&

该项目现已启动,建议迁移到类

要了解更多信息,请参阅.和搜索堆栈溢出以获取许多示例和解释。规范为

您可以直接与数据库交换java.time对象。使用兼容的或更高版本。不需要字符串,也不需要
java.sql.*
classes

从哪里获得java.time类

  • 、和更高版本-标准Java API的一部分,带有捆绑实现。
    • Java9添加了一些次要功能和修复
    • 大多数java.time功能都在中向后移植到Java6和Java7
    • 更高版本的Android捆绑包实现了java.time类

    • 对于早期的Android(您可以使用任务调度器来安排“临时密码删除程序”它将在1小时后执行。一个用户更喜欢正的布尔变量名:
      Boolean accountExpired=false;
      。并且更喜欢原始的
      Boolean
      变量而不是
      Boolean
      引用。最后,更喜欢现代的
      Instant
      类而不是
      Date
      类,因为它有设计问题,并且是long outleted.FYI,非常麻烦的旧日期时间类,如和
      java.text.SimpleDateFormat
      ,现在被内置在java 8和更高版本中的类所取代。请参阅。@Scheduled不允许在特定时间过后使用该函数,这并不是说,也许我错了。您可以在每秒钟调用一个调度程序ond,如果你愿意的话。在你的情况下,每隔几分钟就应该足够了。你能以某种方式获得登录时间,并将其与创建临时密码的时间进行比较吗?然后证明需要这样获得登录时间
      boolean expired = Instant.now().isAfter( user.whenTemporaryPasswordExpires ) ;
      if( expired ) {
          // TODO: Display error message about temp pw expired. Offer new temp pw.
      } else {  // Else, not expired. Accept temporary password.
          // TODO: Check submitted password to see if it matches temporary password issued earlier.
      }