Java Spring启动:电子邮件验证令牌空错误
我正在开发一个JavaSpringBootWeb应用程序,目前正在开发的功能是用户的“重置密码”功能。它类似于我已经成功创建的一个功能,即“注册用户”功能。但是,由于我不知道的原因,“注册用户”功能正在工作,但由于电子邮件验证令牌为空,“重置密码”功能无法工作。这里首先是注册用户的相关控制器:Java Spring启动:电子邮件验证令牌空错误,java,spring-boot,spring-mvc,thymeleaf,email-verification,Java,Spring Boot,Spring Mvc,Thymeleaf,Email Verification,我正在开发一个JavaSpringBootWeb应用程序,目前正在开发的功能是用户的“重置密码”功能。它类似于我已经成功创建的一个功能,即“注册用户”功能。但是,由于我不知道的原因,“注册用户”功能正在工作,但由于电子邮件验证令牌为空,“重置密码”功能无法工作。这里首先是注册用户的相关控制器: @RequestMapping(value="/register", method=RequestMethod.GET) ModelAndView register(M
@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;
}
请注意,我也将“token”打印到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;
...
}
以及发送到用户电子邮件的实际email.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>
是否有人看到可能发生的情况以及令牌为何为空?我想知道thymeleaf如何解析属性${url}和${token}。通常,您应该在forgotUserPassword方法中生成令牌后将其传递给视图。如下所示:modelAndView.addObject(“token”,token);
<!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>
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_.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=?
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, token, token_type, user_id, id) values (?, ?, ?, ?, ?)
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/", "classpath:/resources/", "classpath:/static/", "classpath:/public/", "/"]
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/", "classpath:/resources/", "classpath:/static/", "classpath:/public/", "/"]
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/", "classpath:/resources/", "classpath:/static/", "classpath:/public/", "/"]
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_.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=?
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., 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.323 DEBUG 69549 --- [io-8080-exec-10] 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:57.323 DEBUG 69549 --- [io-8080-exec-10] o.s.web.servlet.view.tiles3.TilesView : View name '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.456 DEBUG 69549 --- [io-8080-exec-10] o.s.web.servlet.DispatcherServlet : Completed 404 NOT_FOUND