知識庫 / Spring RSS 訂閱

清除過期註冊生成的令牌

Security,Spring
HongKong
2
02:50 PM · Dec 06 ,2025

1. 概述

在本教程中,我們將繼續 Spring Security 的 註冊系列,設置一個定時任務來清除過期的 驗證令牌。 在註冊過程中,一個 驗證令牌 會被持久化。 在本文中,我們將演示如何刪除這些實體。

2. 取消過期的令牌

回顧之前文章所述,驗證令牌具有成員 expiryDate,代表令牌的過期時間戳:

@Entity
public class VerificationToken {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String token;

    @OneToOne(targetEntity = User.class, fetch = FetchType.EAGER)
    @JoinColumn(nullable = false, name = "user_id", 
      foreignKey = @ForeignKey(name="FK_VERIFY_USER"))
    private User user;

    private Date expiryDate;
    ...
}

我們將使用此 expiryDate 屬性來生成一個使用 Spring Data 的查詢。

如果您想了解更多關於 Spring Data JPA 的信息,請查看這篇文章。

2.1. 刪除操作

為了方便標記令牌的移除,我們將為我們的 VerificationTokenRepository 添加一個新的方法,用於刪除過期的令牌:

public interface VerificationTokenRepository
  extends JpaRepository<VerificationToken, Long> {

    void deleteByExpiryDateLessThan(Date now);
}

使用 查詢關鍵字 LessThan 表示 Spring Data 的 查詢創建 機制,我們僅對具有 expiryDate 屬性且小於指定時間的 token 感興趣。

請注意,因為 VerificationToken 具有與 User@OneToOne 關聯,並且該關聯標記為 FetchType.EAGER,因此 還會發出 select 語句來填充 User 實體——即使 deleteByExpiryDateLessThan 方法的返回類型為 void:

select 
    *
from 
    VerificationToken verification 
where 
    verification.expiryDate < ?

select 
    * 
from
    user_account user 
where
    user.id=?

delete from 
    VerificationToken
where
    id=?

2.2. 使用 JPQL 刪除

如果不需要將實體加載到持久性上下文中,我們可以創建 JPQL 查詢:

public interface VerificationTokenRepository
  extends JpaRepository<VerificationToken, Long> {

    @Modifying
    @Query("delete from VerificationToken t where t.expiryDate <= ?1")
    void deleteAllExpiredSince(Date now);
}

Hibernate 將不會將實體加載到持久化上下文中。

delete from
    VerificationToken
where
    expiryDate <= ?

3. 安排令牌清除任務

現在我們有一個查詢需要定期執行;我們將利用 Spring 的調度支持並創建一個方法來運行我們的刪除邏輯。

如果您想了解更多關於 Spring Job Scheduling 框架的信息,請查看這篇文章。

3.1. 啓用任務調度

為了啓用任務調度,我們創建一個新的配置類 SpringTaskConfig,並使用 @EnableScheduling 註解進行標註:

@Configuration
@EnableScheduling
public class SpringTaskConfig {
    //
}

3.2. 清除令牌任務

在服務層,我們使用當前時間調用我們的存儲庫。

然後,我們使用 @Scheduled 註解標記該方法,指示 Spring 應該週期性地執行它:

@Service
@Transactional
public class TokensPurgeTask {

    @Autowired
    private VerificationTokenRepository tokenRepository;

    @Scheduled(cron = "${purge.cron.expression}")
    public void purgeExpired() {
        Date now = Date.from(Instant.now());
        tokenRepository.deleteAllExpiredSince(now);
    }
}

3.3. 計劃

我們使用一個屬性來存儲crontab設置的值,以避免更改時重新編譯。在 application.properties 中,我們指定該值:

#    5am every day
purge.cron.expression=0 0 5 * * ?

4. 結論在本文中,我們使用 Spring Data JPA 解決了 VerificationToken 的移除問題。

我們演示了使用屬性表達式創建查詢,以查找具有過期日期小於指定時間的全部令牌。並且,我們創建了一個任務來在運行時調用此邏輯,並將其註冊到 Spring Job Scheduling 框架中,以便定期執行。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.