跟着JHipster学做项目 (14) 账户激活与密码重置

本文详细介绍了JHipster项目中用户注册和账户激活的过程。用户通过邮箱注册,系统验证邮箱和登录名的唯一性,然后发送激活链接。激活链接被点击后,用户账户设置为激活状态。此外,还展示了密码重置的流程,包括发送重置链接,用户在规定时间内完成密码更新。整个过程涉及到的关键实体包括User对象的activated和activationKey属性,以及相关的服务和控制器方法。

在JHipster项目中,用户使用邮箱进行注册,注册成功后将发送账户激活链接到邮箱,用户点击链接后,激活成功。

AccountResource类代码:

    /**
     * {@code POST  /register} : register the user.
     *
     * @param managedUserVM the managed user View Model.
     * @throws InvalidPasswordException {@code 400 (Bad Request)} if the password is incorrect.
     * @throws EmailAlreadyUsedException {@code 400 (Bad Request)} if the email is already used.
     * @throws LoginAlreadyUsedException {@code 400 (Bad Request)} if the login is already used.
     */
    @PostMapping("/register")
    @ResponseStatus(HttpStatus.CREATED)
    public void registerAccount(@Valid @RequestBody ManagedUserVM managedUserVM) {
        if (isPasswordLengthInvalid(managedUserVM.getPassword())) {
            throw new InvalidPasswordException();
        }
        User user = userService.registerUser(managedUserVM, managedUserVM.getPassword());
        mailService.sendActivationEmail(user);
    }

UserService类代码:

    public User registerUser(AdminUserDTO userDTO, String password) {
        userRepository
            .findOneByLogin(userDTO.getLogin().toLowerCase())
            .ifPresent(
                existingUser -> {
                    boolean removed = removeNonActivatedUser(existingUser);
                    if (!removed) {
                        throw new UsernameAlreadyUsedException();
                    }
                }
            );
        userRepository
            .findOneByEmailIgnoreCase(userDTO.getEmail())
            .ifPresent(
                existingUser -> {
                    boolean removed = removeNonActivatedUser(existingUser);
                    if (!removed) {
                        throw new EmailAlreadyUsedException();
                    }
                }
            );
        User newUser = new User();
        String encryptedPassword = passwordEncoder.encode(password);
        newUser.setLogin(userDTO.getLogin().toLowerCase());
        // new user gets initially a generated password
        newUser.setPassword(encryptedPassword);
        newUser.setFirstName(userDTO.getFirstName());
        newUser.setLastName(userDTO.getLastName());
        if (userDTO.getEmail() != null) {
            newUser.setEmail(userDTO.getEmail().toLowerCase());
        }
        newUser.setImageUrl(userDTO.getImageUrl());
        newUser.setLangKey(userDTO.getLangKey());
        // new user is not active
        newUser.setActivated(false);
        // new user gets registration key
        newUser.setActivationKey(RandomUtil.generateActivationKey());
        Set<Authority> authorities = new HashSet<>();
        authorityRepository.findById(AuthoritiesConstants.USER).ifPresent(authorities::add);
        newUser.setAuthorities(authorities);
        userRepository.save(newUser);
        log.debug("Created Information for User: {}", newUser);
        return newUser;
    }

这里两个关键User字段:activated, activationKey,在User实体类中activated属于必需属性,而activationKey则属于临时属性,JHipster采用@JsonIgnore进行注解,当进行序列化或者反序列化时,Pojo对象将不转换该属性信息。如下:

private boolean activated = false;

    @Size(min = 2, max = 10)
    @Field("lang_key")
    private String langKey;

    @Size(max = 256)
    @Field("image_url")
    private String imageUrl;

    @Size(max = 20)
    @Field("activation_key")
    @JsonIgnore
    private String activationKey;

    @Size(max = 20)
    @Field("reset_key")
    @JsonIgnore
    private String resetKey;

    @Field("reset_date")
    private Instant resetDate = null;

用户点击邮件中的链接,例如:

http://127.0.0.1:9000/account/activate?key=5RfmrcsxqxbgoBg2GGjq

后端会根据key值进行校验,代码如下:

    public Optional<User> activateRegistration(String key) {
        log.debug("Activating user for activation key {}", key);
        return userRepository
            .findOneByActivationKey(key)
            .map(
                user -> {
                    // activate given user for the registration key.
                    user.setActivated(true);
                    user.setActivationKey(null);
                    userRepository.save(user);
                    log.debug("Activated user: {}", user);
                    return user;
                }
            );
    }

根据同样原理,当用户需要重置密码时,用户填写注册时使用的邮箱并提交重置密码请求,系统会发送包含密码重置链接邮件:

http://127.0.0.1:9000/account/reset/finish?key=F6WMyIwMSeGzY4E9TxS3

点击链接后,显示填写重置密码的页面,提交后系统根据key进行查询,并且限制链接24小时内有效,代码如下:

    public Optional<User> completePasswordReset(String newPassword, String key) {
        log.debug("Reset user password for reset key {}", key);
        return userRepository
            .findOneByResetKey(key)
            .filter(user -> user.getResetDate().isAfter(Instant.now().minusSeconds(86400)))
            .map(
                user -> {
                    user.setPassword(passwordEncoder.encode(newPassword));
                    user.setResetKey(null);
                    user.setResetDate(null);
                    userRepository.save(user);
                    return user;
                }
            );
    }

Good Luck,

Cheers!

### MPU6050启动失败解决方案 当遇到MPU6050传感器无法正常初始化或工作的情况时,通常可以从硬件连接、配置文件设置以及驱动程序调试等方面排查问题。 对于硬件连接部分,确保I2C总线上的上拉电阻已经正确安装,并且电源电压稳定[^1]。错误的硬件连接可能导致通信失败,进而引起启动异常。 关于配置方面,如果是在嵌入式Linux环境下开发,则需确认内核配置是否包含了必要的选项来支持该器件。例如,在BeagleBone Black平台上,可参照`am335x_evm_defconfig`模板创建适合目标板的具体配置文件`am335x_<myboard>_defconfig`。这一步骤有助于启用正确的外设接口并加载相应的模块。 针对具体的应用层实现,可以借鉴Ardupilot项目中的法来进行故障排除。该项目通过特定算法处理可能出现的各种错误情况,从而提高系统的鲁棒性和可靠性[^2]。类似地,在自己的应用程序里加入类似的健壮性设计能够有效减少因外部因素造成的启动失败现象。 最后,考虑到USB转接可能带来的兼容性问题,了解不同厂商生产的USB设备所使用的Vendor ID (VID) 和 Product ID (PID),可以帮助识别潜在冲突并采取措施规避它们[^3]。 ```c // 示例代码片段展示如何读取状态寄存器以验证MPU6050是否成功初始化 uint8_t status; if (!i2c_read_register(MPU6050_ADDRESS, WHO_AM_I_REG, &status)) { printf("Failed to read WHO AM I register\n"); } else if (status != MPU6050_WHOAMI_VALUE){ printf("Incorrect device on bus or not initialized properly.\n"); } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值