spring 用户如何在本网站更改密码?

jv4diomz  于 2022-12-26  发布在  Spring
关注(0)|答案(1)|浏览(117)

我正在使用Sping Boot 创建一个网站。我有一个模板(thymeleaf),用户可以在其中更改密码。但是当用户写入新密码时,密码不会更改。它会重定向到我的主页,但没有任何React。没有错误。
更改密码的后端:
第一个月

@GetMapping("/reset") public String infoLogin(Model model){ 
model.addAttribute("users",new Users()); return "login/reset";
}

@PostMapping("/reset/{username}") public String pass(@PathVariable("username") String username){ 
userService.findUsername(username); return "redirect:/index"; 
}

@Service

@Transactional @PreAuthorize("#username == authentication.name") public Users findUsername(String username){ 
return this.usersRepo.findByUsername(username); 
}

@Repository

@Repository public interface UsersRepo extends JpaRepository<Users,Long> {

Users findByUsername(String username);
}

安全配置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter  {
    
    private final UserService userService;
    
    @Autowired
    public SecurityConfig( UserService userService) {
        this.userService = userService;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
                .antMatchers("/guest/**","/index/**","/images/**","/css/**","/fonts/**","/js/**","/scripts/**","/server/**","/src/**")
                .permitAll()
                .antMatchers("/admin/*","/user/*").hasAuthority("ADMIN")
                .antMatchers("/user/*").hasAuthority("USER")
                .anyRequest().authenticated()
                          .and().formLogin().loginPage("/guest/login").defaultSuccessUrl("/index",true).permitAll()
                .and().rememberMe().rememberMeCookieName("remember").rememberMeParameter("remember")
                .and().logout().deleteCookies("remember").permitAll()
                .and()
                .exceptionHandling().accessDeniedPage("/guest/403");
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       User.UserBuilder userBuilder=User.withDefaultPasswordEncoder();
       auth.userDetailsService(userService);
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return NoOpPasswordEncoder.getInstance();
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

模板:

<form method="post"  th:action="@{/user/reset/{username}(username=${#authentication.principal.getUsername})}" th:object="${users}">
    <input type="hidden" th:field="*{id}">
    <div class="form-group">
        <label>Username</label>
        <input type="text" name="username" class="form-control" th:field="*{username}">
    </div>
    <div class="form-group">
        <label>New Password</label>
        <input type="password" id="password" th:field="*{password}" class="form-control">
    </div>
    <div class="form-group text-right">
        <input class="btn btn-primary btn-block" type="submit">
    </div>
</form>

在数据库中,它大致如下所示:
| 身份证|电子邮件|用户名|密码|...|
| - ------|- ------|- ------|- ------|- ------|
| 三十四|something@gmail.com|迈赫迪22|小行星1234| ...|

@Entity
@Table(name = "tbl_users")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Users implements Serializable, UserDetails {

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

    private boolean enabled =true;

    @NotBlank
    @Size(min = 4,max = 10)
    private String username;
    @NotBlank
    @Size(min = 2,max = 20)
    private String name;
    @Email
    @Column(unique = true)
    private String email;
    @NotBlank
    @Size(min = 8,max = 30)
    private String password;

    @OneToMany(mappedBy = "user")
    private List<Posts> posts;

    @ElementCollection(targetClass = Roles.class,fetch = FetchType.EAGER)
    @CollectionTable(name = "authorities",joinColumns =
    @JoinColumn(name = "username",referencedColumnName = "username") )
    @Enumerated(EnumType.STRING)
    private List<Roles> roles;

    public Users() {
    }

    public Users(String username, String name, String email, String password) {
        this.username = username;
        this.name = name;
        this.email = email;
        this.password = password;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public List<Posts> getPosts() {
        return posts;
    }

    public void setPosts(List<Posts> posts) {
        this.posts = posts;
    }

    public void setEnabled(boolean enable) {
        this.enabled = enable;
    }

    public List<Roles> getRoles() {
        return roles;
    }

    public void setRoles(List<Roles> roles) {
        this.roles = roles;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return roles;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }
}
yqhsw0fo

yqhsw0fo1#

但当用户写入新密码时,密码不会更改。
您只是没有在任何地方更改密码。当您发送表单并调用/reset/{username}时,您甚至没有查看密码。

@PostMapping("/reset/{username}")
public String pass(@PathVariable("username") String username, @RequestParam("password") String password){ 
    userService.changePassword(username,password);
    return "redirect:/index"; 
}

并为您服务:

@Autowired
private PasswordEncoder passwordEncoder;

@Transactional
@PreAuthorize("#username == authentication.name")
public void changePassword(String username, String password){ 
    Users user= this.usersRepo.findByUsername(username); 
    user.setPassword(this.passwordEncoder.encode(password));
    this.usersRepo.save(user);
}

除此之外,你应该对你的密码进行哈希运算。想象一下,某个未经授权的人访问了你的数据库。他们可以访问你所有用户的密码。
对于散列密码,请将PasswordEncoder更改为不使用NoOpPasswordEncoder

@Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

还要注意,您不应该向用户显示他们自己的密码(或哈希)。
为此,请更改

<input type="password" id="password" th:field="*{password}" class="form-control">

<input type="password" id="password" name="password" class="form-control">

我还建议您不要依赖@PreAuthorize来检查用户是否真的更改了自己的密码,相反,我会执行以下操作:

@PostMapping("/reset")
public String pass(Authentication authentication, @RequestParam("password") String password){ 
    userService.changePassword(authentication.getName(), password);
    return "redirect:/index"; 
}

这总是改变当前用户的密码.它也不要求用户名从前端发送允许你简化你的表单:

<form method="post" th:action="@{/user/reset" th:object="${users}">

如果没有th:object,整个表单可能如下所示:

<form method="post" th:action="@{/user/reset"">
    <input type="hidden" th:field="*{id}">
    <div class="form-group">
        <label>Username</label>
        <label th:text="${users.username}"></label>
    </div>
    <div class="form-group">
        <label>New Password</label>
        <input type="password" id="password" name="password" class="form-control">
    </div>
    <div class="form-group text-right">
        <input class="btn btn-primary btn-block" type="submit">
    </div>
</form>

相关问题