Java Spring Boot:电子邮件验证令牌为空错误

问题描述

我正在开发Java Spring Boot Web App,目前正在使用的功能是为用户提供的“重置密码”功能。它类似于我已经成功创建的功能,即“注册用户”功能。但是,由于某些我不知道的原因,由于电子邮件验证令牌为空,“注册用户”功能正在运行,但“重置密码”功能却不起作用。首先是用于注册用户的相关控制器:

    @RequestMapping(value="/register",method=RequestMethod.GET)
    ModelAndView register(ModelAndView modelAndView) throws FileNotFoundException {
        SiteUser user = new SiteUser(); 
        modelAndView.getModel().put("user",user);
        modelAndView.setViewName("app.register");
        return modelAndView;
    }
    
    
    @RequestMapping(value="/register",method=RequestMethod.POST)
    ModelAndView register(ModelAndView modelAndView,@ModelAttribute(value="user") @Valid SiteUser user,BindingResult result) {
        modelAndView.setViewName("app.register");
        
        if(!result.hasErrors()) {
            userService.register(user);
            String token = userService.createEmailVerificationTokenRegister(user).toString();
            emailService.sendVerificationEmailRegister(user.getEmail(),token);
            modelAndView.setViewName("redirect:/verifyEmail");
        }
        

        return modelAndView;
    }

    @RequestMapping("/confirmRegister")
    ModelAndView registrationConfirmed(ModelAndView modelAndView,@RequestParam("t") String tokenString) {
        
        VerificationToken token = userService.getVerificationToken(tokenString);
        
        System.out.println("verification token " + token);
        
        if(token == null) {
            modelAndView.setViewName("redirect:/invalidUser");
            userService.deleteToken(token);
            return modelAndView;
        }
        
        Date expiryDate = token.getExpiryDate();
        
        if(expiryDate.before(new Date())) {
            modelAndView.setViewName("redirect:/expiredToken");
            userService.deleteToken(token);
            return modelAndView;
        }
        
        SiteUser user = token.getUser();
        
        if (user == null) {
            modelAndView.setViewName("redirect:/invalidUser");
            userService.deleteToken(token);
            return modelAndView;
        }
        
        userService.deleteToken(token);
        user.setEnabled(true);
        userService.save(user);
        
        modelAndView.getModel().put("message",registrationConfirmedMessage);
        modelAndView.setViewName("app.message");
        return modelAndView;
    }

请注意,我也将“令牌”打印到System.out,在这种情况下,我得到了一个值,并且此方法成功运行。接下来,我尝试使用几乎相同的方法来实现“重置密码”功能。这是控制器:

    @RequestMapping(value="/forgotPassword",method=RequestMethod.GET)
    ModelAndView displayResetPassword(ModelAndView modelAndView,SiteUser user) {
        modelAndView.getModel().put("user",user);
        //modelAndView.addObject("user",user);
        modelAndView.setViewName("app.forgotPassword");
        //System.out.println("*********** GET **********");
        return modelAndView;
    }

    @RequestMapping(value="/forgotPassword",method=RequestMethod.POST)
    ModelAndView forgotUserPassword(ModelAndView modelAndView,@ModelAttribute(value="user") SiteUser user) {
        SiteUser existingUser = userRepo.findByEmail(user.getEmail());
        
        //System.out.println(user.getEmail());
        //userEmail=existingUser.getEmail();
        //userPW=existingUser.getPassword();
        //System.out.println(userEmail);
        //System.out.println(userPW);
        
        System.out.println(existingUser.getEmail());
        
        
        if (existingUser.getEmail() == null)
        {
            modelAndView.setViewName("redirect:/invalidUser");
            System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&& if");
        }
        
        else {
            System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&& else");
            String token = userService.createEmailVerificationTokenForgotPassword(existingUser).toString();

            emailService.sendVerificationEmailForgotPassword(existingUser.getEmail(),token);
            modelAndView.setViewName("redirect:/verifyEmail");
        }
        
        return modelAndView;
    }

    @RequestMapping("/confirmReset")
    ModelAndView confirmReset(ModelAndView modelAndView,@RequestParam("t") String tokenString) {
        
        System.out.println("here");
        
        VerificationToken token = userService.getVerificationToken(tokenString);
        
        System.out.println("verification token " + token);
        
        System.out.println("not here");
        
        if(token == null) {
            modelAndView.setViewName("redirect:/invalidUser");
            userService.deleteToken(token);
            System.out.println("*************** ONE ************");
            return modelAndView;
        }
        
        Date expiryDate = token.getExpiryDate();
        
        if(expiryDate.before(new Date())) {
            modelAndView.setViewName("redirect:/expiredToken");
            userService.deleteToken(token);
            System.out.println("*************** TWO ************");
            return modelAndView;
        }
        
        SiteUser user = token.getUser();
        
        System.out.println("************ USER IS HERE: " + user);
        
        if (user == null) {
            modelAndView.setViewName("redirect:/invalidUser");
            userService.deleteToken(token);
            System.out.println("*************** THREE ************");
            return modelAndView;
        }
        
        user.setEnabled(true);
        userRepo.save(user);
        modelAndView.addObject("user",user);
        modelAndView.addObject("email",user.getEmail());
        modelAndView.setViewName("redirect:/resetPassword");
        userService.deleteToken(token);
        
        return modelAndView;
    }

当我尝试将'token'打印到System.out时,这里的区别是该值为null。我不知道怎么回事,因此我无法重置密码。

出于良好的考虑,这也是VerificationToken类变量,未显示getter / setter:

@Entity
@Table(name="Verification")
public class VerificationToken {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="id")
    private Long id;
    
    @Column(name="token")
    private String token;
    
    @OneToOne(targetEntity=SiteUser.class) // for every user,there's 1 verification token
    @JoinColumn(name="user_id",nullable=false) // foreign key to users table
    private SiteUser user;
    
    @Column(name="expiry_date")
    @Temporal(TemporalType.TIMESTAMP)
    private Date expiryDate;
    
    @Column(name="token_type")
    @Enumerated(EnumType.STRING)
    private TokenType tokenType;
...
}

以及发送到用户电子邮件的实际电子邮件.html文件。首先,forgotPassword.html,它当然不起作用:

<!DOCTYPE html>
<html>

<th:block xmlns:th="http://www.thymeleaf.org">

<p>Please click <a th:href="@{${url} + '/confirmReset?t=' + ${token}}">here</a> to verify your email address and reset your password.</p>
<!-- @{} is a thymeleaf expression -->
</th:block>

</html>

然后是verifyEmail.html,它当然是用于注册新用户的

<!DOCTYPE html>
<html>

<th:block xmlns:th="http://www.thymeleaf.org">


<p>Thank you for registering for the bcoreHW site!</p>
<p>Please click <a th:href="@{${url} + '/confirmRegister?t=' + ${token}}">here</a> to verify your email address.</p>
<!-- @{} is a thymeleaf expression -->
</th:block>

</html>

最后,这是堆栈跟踪的相关部分。请注意System.out.println()语句以及所显示的内容与未显示的内容:

20-10-15 00:07:54.287 DEBUG 69549 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : POST "/forgotPassword",parameters={masked}
2020-10-15 00:07:54.288 DEBUG 69549 --- [nio-8080-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to bcoreHW.controllers.AuthController#forgotUserPassword(ModelAndView,SiteUser)
2020-10-15 00:07:54.378 DEBUG 69549 --- [nio-8080-exec-2] org.hibernate.SQL                        : select siteuser0_.user_id as user_id1_3_,siteuser0_.email as email2_3_,siteuser0_.enabled as enabled3_3_,siteuser0_.password as password4_3_,siteuser0_.role as role5_3_ from users siteuser0_ where siteuser0_.email=?
Hibernate: select siteuser0_.user_id as user_id1_3_,siteuser0_.role as role5_3_ from users siteuser0_ where siteuser0_.email=?
admin@admin.com
&&&&&&&&&&&&&&&&&&&&&&&&& else
2020-10-15 00:07:54.402 DEBUG 69549 --- [nio-8080-exec-2] org.hibernate.SQL                        : select next_val as id_val from hibernate_sequence for update
Hibernate: select next_val as id_val from hibernate_sequence for update
2020-10-15 00:07:54.403 DEBUG 69549 --- [nio-8080-exec-2] org.hibernate.SQL                        : update hibernate_sequence set next_val= ? where next_val=?
Hibernate: update hibernate_sequence set next_val= ? where next_val=?
2020-10-15 00:07:54.417 DEBUG 69549 --- [nio-8080-exec-2] org.hibernate.SQL                        : insert into forgot_password (expiry_date,token,token_type,user_id,id) values (?,?,?)
Hibernate: insert into forgot_password (expiry_date,?)
2020-10-15 00:07:54.425 DEBUG 69549 --- [nio-8080-exec-2] o.s.web.servlet.view.RedirectView        : View name 'redirect:',model {}
2020-10-15 00:07:54.426 DEBUG 69549 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Completed 302 FOUND
2020-10-15 00:07:54.434 DEBUG 69549 --- [nio-8080-exec-6] o.s.web.servlet.DispatcherServlet        : GET "/verifyEmail",parameters={}
2020-10-15 00:07:54.434 DEBUG 69549 --- [nio-8080-exec-6] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to bcoreHW.controllers.AuthController#verifyEmail()
2020-10-15 00:07:54.436 DEBUG 69549 --- [nio-8080-exec-6] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html,application/xhtml+xml,image/avif,image/webp,image/apng,application/xml;q=0.9,application/signed-exchange;v=b3;q=0.9,*/*;q=0.8]
2020-10-15 00:07:54.436 DEBUG 69549 --- [nio-8080-exec-6] o.s.web.servlet.view.tiles3.TilesView    : View name 'app.verifyEmail',model {}
2020-10-15 00:07:54.507 DEBUG 69549 --- [nio-8080-exec-6] o.s.web.servlet.DispatcherServlet        : Completed 200 OK
2020-10-15 00:07:54.528 DEBUG 69549 --- [nio-8080-exec-8] o.s.web.servlet.DispatcherServlet        : GET "/css/bootstrap.min.css",parameters={}
2020-10-15 00:07:54.528 DEBUG 69549 --- [nio-8080-exec-7] o.s.web.servlet.DispatcherServlet        : GET "/css/main.css",parameters={}
2020-10-15 00:07:54.528 DEBUG 69549 --- [nio-8080-exec-5] o.s.web.servlet.DispatcherServlet        : GET "/js/bootstrap.min.js",parameters={}
2020-10-15 00:07:54.529 DEBUG 69549 --- [nio-8080-exec-8] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler ["classpath:/META-INF/resources/","classpath:/resources/","classpath:/static/","classpath:/public/","/"]
2020-10-15 00:07:54.529 DEBUG 69549 --- [nio-8080-exec-7] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler ["classpath:/META-INF/resources/","/"]
2020-10-15 00:07:54.529 DEBUG 69549 --- [nio-8080-exec-5] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler ["classpath:/META-INF/resources/","/"]
2020-10-15 00:07:54.529 DEBUG 69549 --- [nio-8080-exec-9] o.s.web.servlet.DispatcherServlet        : GET "/img/bcore-bride+AI.png",parameters={}
2020-10-15 00:07:54.532 DEBUG 69549 --- [nio-8080-exec-7] o.s.web.servlet.DispatcherServlet        : Completed 200 OK
2020-10-15 00:07:54.532 DEBUG 69549 --- [nio-8080-exec-9] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler ["classpath:/META-INF/resources/","/"]
2020-10-15 00:07:54.532 DEBUG 69549 --- [nio-8080-exec-5] o.s.web.servlet.DispatcherServlet        : Completed 200 OK
2020-10-15 00:07:54.533 DEBUG 69549 --- [nio-8080-exec-8] o.s.web.servlet.DispatcherServlet        : Completed 200 OK
2020-10-15 00:07:54.535 DEBUG 69549 --- [nio-8080-exec-9] o.s.web.servlet.DispatcherServlet        : Completed 200 OK
2020-10-15 00:07:57.309 DEBUG 69549 --- [io-8080-exec-10] o.s.web.servlet.DispatcherServlet        : GET "/confirmReset?t=6e374e4e-0113-4fae-92f7-e8b5c97755d9",parameters={masked}
2020-10-15 00:07:57.309 DEBUG 69549 --- [io-8080-exec-10] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to bcoreHW.controllers.AuthController#confirmReset(ModelAndView,String)
here
2020-10-15 00:07:57.315 DEBUG 69549 --- [io-8080-exec-10] org.hibernate.SQL                        : select verificati0_.id as id1_4_,verificati0_.expiry_date as expiry_d2_4_,verificati0_.token as token3_4_,verificati0_.token_type as token_ty4_4_,verificati0_.user_id as user_id5_4_ from verification verificati0_ where verificati0_.token=?
Hibernate: select verificati0_.id as id1_4_,verificati0_.user_id as user_id5_4_ from verification verificati0_ where verificati0_.token=?
verification token null
not here
2020-10-15 00:07:57.322 DEBUG 69549 --- [io-8080-exec-10] .m.m.a.ExceptionHandlerExceptionResolver : Using @ExceptionHandler bcoreHW.controllers.GlobalExceptionHandler#defaultErrorHandler(HttpServletRequest,Exception)
2020-10-15 00:07:57.322 DEBUG 69549 --- [io-8080-exec-10] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.dao.InvalidDataAccessApiUsageException: Entity must not be null!; nested exception is java.lang.IllegalArgumentException: Entity must not be null!] to ModelAndView [view="app.exception"; model={message=An error occurred.,url=http://localhost:8080/confirmReset,exception=org.springframework.dao.InvalidDataAccessApiUsageException: Entity must not be null!; nested exception is java.lang.IllegalArgumentException: Entity must not be null!}]
2020-10-15 00:07:57.322 DEBUG 69549 --- [io-8080-exec-10] o.s.web.servlet.DispatcherServlet        : Using resolved error view: ModelAndView [view="app.exception"; model={message=An error occurred.,exception=org.springframework.dao.InvalidDataAccessApiUsageException: Entity must not be null!; nested exception is java.lang.IllegalArgumentException: Entity must not be null!}]
2020-10-15 00:07:57.323 DEBUG 69549 --- [io-8080-exec-10] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html,*/*;q=0.8]
2020-10-15 00:07:57.323 DEBUG 69549 --- [io-8080-exec-10] o.s.web.servlet.view.tiles3.TilesView    : View name 'app.exception',model {message=An error occurred.,exception=org.springframework.dao.InvalidDataAccessApiUsageException: Entity must not be null!; nested exception is java.lang.IllegalArgumentException: Entity must not be null!}
2020-10-15 00:07:57.456 DEBUG 69549 --- [io-8080-exec-10] o.s.web.servlet.DispatcherServlet        : Completed 404 NOT_FOUND

有人看到发生了什么,为什么令牌为空?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...