如何在Thymeleaf中向控制器传递未展示的登录用户信息
解决Thymeleaf自动传递登录用户名到Spring控制器的方案
针对密码修改场景,无需用户手动输入用户名,可通过以下两种方式实现自动传递登录用户的username字段:
方法一:在表单中添加隐藏字段
利用Thymeleaf的隐藏输入框,将登录用户的用户名自动填充并随表单提交,无需展示给用户:
修改你的视图代码,在表单内添加隐藏字段,并修正表单字段的绑定方式(推荐使用th:field替代th:name以实现更准确的模型绑定):
<form th:action="@{/changePassword}" th:object="${user}" method="post"> <!-- 添加隐藏字段,自动填充登录用户名 --> <input type="hidden" th:field="*{username}" th:value="${#httpServletRequest.remoteUser}" /> <div class="col-md-6 form-group"> <label>Old Password</label> <input type="text" class="form-control" th:field="*{oldPassword}"> </div> <div class="col-md-6 form-group"> <label>New Password</label> <input type="password" class="form-control" th:field="*{password}"> </div> <div class="col-md-6 form-group"> <label>Confirm Password</label> <input type="password" class="form-control" th:field="*{confirmPassword}"> <!-- 注意:需在User模型中添加confirmPassword字段用于前端校验,或通过JS校验两次输入一致 --> </div> <button type="submit" onclick="savePass()">Change Password</button> </form>
提交表单后,Spring会自动将隐藏字段的username值绑定到@ModelAttribute的User对象中。
方法二:在控制器中直接获取登录用户(更安全)
无需在视图中做任何修改,直接从Spring Security的上下文获取当前登录用户的用户名,避免前端字段被篡改的风险:
修改控制器代码,通过@AuthenticationPrincipal注解或SecurityContextHolder获取当前用户:
import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.userdetails.UserDetails; @PostMapping("/changePassword") public String updatePassword(@ModelAttribute("user") User user, @AuthenticationPrincipal UserDetails currentUser, Model model) { // 获取当前登录用户的用户名 String username = currentUser.getUsername(); // 填充到User对象中 user.setUsername(username); // 加密新密码 user.setPassword(passwordEncoder.encode(user.getPassword())); // 执行密码修改逻辑 userService.changeUserPassword(username, user.getPassword()); return "display"; }
如果不使用@AuthenticationPrincipal,也可以通过SecurityContextHolder直接获取:
import org.springframework.security.core.context.SecurityContextHolder; // ... String username = SecurityContextHolder.getContext().getAuthentication().getName();
额外提示
- 密码修改功能建议增加旧密码校验:先根据用户名查询数据库中的用户,使用
passwordEncoder.matches(user.getOldPassword(), 数据库存储的加密密码)验证旧密码是否正确,再执行修改操作。 - 前端需添加新密码确认校验:通过JS判断新密码和确认密码输入是否一致,避免无效提交。
内容的提问来源于stack exchange,提问作者Michu93
相关产品推荐
相关产品推荐

