在Spring Boot中实现Google Authenticator动态码验证,可以通过以下步骤进行:

1. 引入依赖

首先,在你的pom.xml文件中引入必要的依赖:

<dependencies>
    <!-- Spring Boot Dependencies -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <!-- Google Authenticator library -->
    <dependency>
        <groupId>com.warrenstrange</groupId>
        <artifactId>googleauth</artifactId>
        <version>1.4.0</version>
    </dependency>
</dependencies>

2. 用户实体

创建一个包含TOTP密钥的用户实体。

import javax.persistence.*;

@Entity
public class User {

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

    private String username;
    private String password;
    private String email;
    private String totpSecret;
    private boolean isTotpVerified;

    // getters and setters
}

3. 用户存储库

创建一个存储库接口。

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
    User findByUsername(String username);
}

4. 服务层

创建一个服务类来处理TOTP生成和验证。

import com.warrenstrange.googleauth.GoogleAuthenticator;
import com.warrenstrange.googleauth.GoogleAuthenticatorKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    private final GoogleAuthenticator gAuth = new GoogleAuthenticator();

    public String generateTotpSecret(String username) {
        GoogleAuthenticatorKey key = gAuth.createCredentials();
        User user = userRepository.findByUsername(username);
        user.setTotpSecret(key.getKey());
        userRepository.save(user);
        return key.getKey();
    }

    public boolean verifyTotpCode(String username, int code) {
        User user = userRepository.findByUsername(username);
        return gAuth.authorize(user.getTotpSecret(), code);
    }
}

5. 控制器

创建控制器来处理启用和验证2FA的请求。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class TwoFactorAuthController {

    @Autowired
    private UserService userService;

    @GetMapping("/enable-2fa")
    public String enable2fa(Model model) {
        // 假设用户已经登录并且用户名为 "user"
        String username = "user";
        String secret = userService.generateTotpSecret(username);
        model.addAttribute("secret", secret);
        // 生成QR码的URI
        String otpUri = "otpauth://totp/YourApp:" + username + "?secret=" + secret + "&issuer=YourApp";
        model.addAttribute("otpUri", otpUri);
        return "enable-2fa";
    }

    @PostMapping("/verify-2fa")
    public String verify2fa(@RequestParam("code") int code, Model model) {
        // 假设用户已经登录并且用户名为 "user"
        String username = "user";
        if (userService.verifyTotpCode(username, code)) {
            model.addAttribute("message", "2FA 验证成功");
            return "success";
        } else {
            model.addAttribute("message", "2FA 验证失败");
            return "verify-2fa";
        }
    }

    @GetMapping("/verify-2fa")
    public String showVerify2faForm() {
        return "verify-2fa";
    }
}

6. Thymeleaf模板

创建两个Thymeleaf模板文件:enable-2fa.htmlverify-2fa.html

enable-2fa.html:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Enable 2FA</title>
</head>
<body>
<h1>Enable 2FA</h1>
<p>Scan this QR code with Google Authenticator:</p>
<img th:src="@{'https://chart.googleapis.com/chart?cht=qr&chs=200x200&chl=' + ${otpUri}}"/>
<p>Or use this secret key: <span th:text="${secret}"></span></p>
<a href="/verify-2fa">Verify 2FA</a>
</body>
</html>

verify-2fa.html:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Verify 2FA</title>
</head>
<body>
<h1>Verify 2FA</h1>
<form action="/verify-2fa" method="post">
    <label for="code">Enter the code from Google Authenticator:</label>
    <input type="text" id="code" name="code"/>
    <button type="submit">Verify</button>
</form>
<p th:text="${message}"></p>
</body>
</html>

以上代码展示了如何在Spring Boot项目中实现Google Authenticator的动态码验证。你可以根据需要进行扩展和优化,比如集成用户认证、加密存储密钥等。