恢复密码时,我的项目中会生成一个密码,您可以使用该密码登录帐户并更改密码,我不明白如何按时间限制临时密码字段?假设用户可以使用此密码登录一个小时,我有一个密码的日期字段,但是我不知道该与什么进行比较
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;
答案 0 :(得分:3)
Instant // Represents a moment in UTC.
.now() // Capture the current moment, as seen through the wall-clock time of UTC.
.ifAfter( // Compare one `Instant` object to another.
user.whenTemporaryPasswordExpires // This stored moment (an `Instant`) represents an hour later than the current moment captured when the temporary password was issued.
) // Returns a boolean.
跟踪密码过期的时间。因此,将validityTime
变量的名称更改为whenTemporaryPasswordExpires
。
当用户尝试再次登录时,您将捕获当前时刻,然后将其与存储的whenTemporaryPasswordExpires
进行比较。
请勿使用java.util.Date
。这是Java最早版本中可怕的日期时间类之一。这些遗留类完全由 java.time 类在采用JSR 310之前取代。
两个阶段的第一阶段,设置生成临时密码时的到期时间。
捕获当前时刻。
Instant instant = Instant.now() ; // Capture the current moment in UTC.
确定临时密码可以使用多长时间的业务策略。使用Duration
可以按照天(24小时的时间,不是日历天),小时,分钟和秒来跟踪时间跨度。
Duration d = Duration.ofHours( 1 ) ; // Policy says temporary password is good for one hour.
做一些日期时间数学运算,将时间跨度(Duration
对象)添加到Instant
以获得代表未来时刻的新Instant
。请注意 java.time 如何使用immutable objects,因此将产生一个新的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.
}
请注意,以上所有代码均使用UTC。到期逻辑无需费时。如果要显示到期时间,请搜索堆栈溢出以了解ZoneId
,ZonedDateTime
和DateTimeFormatter.ofLocalized…
。
在上面的讨论中,我忽略了一个显而易见的问题,即我们从不存储密码。我们使用盐化和散列,但这是完全不同的讨论。
java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和SimpleDateFormat
。
目前位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
在哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval
,YearWeek
,YearQuarter
和more。
答案 1 :(得分:0)
您可以使用ScheduledTasks重置所有已过期的临时密码,并设置一个标志,指示临时密码不再有效。