Spring Security - 重定向到另一个 .html 页面

问题描述 投票:0回答:1

我想创建一个功能,允许用户在电子邮件验证期间设置密码。因此,当管理员创建用户帐户时,他会收到一封包含链接的电子邮件: http://localhost:8080/api/v1/students/set-password.html?token=d9bbd9b6-d94b-4aac-b4fe-756402eeb6ad

当用户输入链接时,电子邮件将得到验证,并且应出现 set-password.html 页面,用户可以在其中设置密码。

每次我尝试输入此链接时,都会自动重定向到 http://localhost:8080/login.html。

我认为我的安全配置有问题,我尝试更改一些内容,但没有成功。有什么问题,我怎样才能轻松地重定向它或者我应该如何做得更好?

StudentService类中的SetPassword方法:


@Transactional
public boolean setPassword(String token, String password, String confirmPassword) {
if (!password.equals(confirmPassword)) {
throw new IllegalArgumentException("Passwords do not match.");
}

Student student = studentRepository.findByVerificationToken(UUID.fromString(token))
.orElseThrow(() -\> new IllegalArgumentException("Invalid or expired token."));

        if (!student.isEmailVerified()) {
            throw new IllegalStateException("Email is not verified.");
        }
    
        student.setPassword(passwordEncoder.encode(password));
        student.setVerificationToken(null); // Invalidate the token after password is set
        studentRepository.save(student);
        return true;
    }

学生控制器:

package pl.studia.university.controller;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/students")
@CrossOrigin
public class StudentController {

    private final StudentService studentService;
    
    
    @GetMapping
    public Page<StudentDto> search(@RequestParam(value = "search", required = false) String search, Pageable pageable) {
        return studentService.search(search, pageable);
    }
    
    @PostMapping("/create")
    @ResponseStatus(HttpStatus.CREATED)
    public StudentDto create(@RequestBody CreateStudentCommand command) {
        if (!PostalCodeValidator.validatePostalCode(command.getAddress().getPostalCode())) {
            throw new InvalidPostalCodeFormatException("Invalid Postal code format");
        }
        if (!PeselValidator.validatePeselNumber(command.getPeselNumber())) {
            throw new InvalidPeselFormatException("Invalid Pesel format");
        }
        return studentService.create(command);
    }

//    @GetMapping("/confirm")
//    public ApiResponse confirmEmail(@RequestParam("token") String token) {
//        boolean isVerified = studentService.confirmEmail(token);
//        if (isVerified) {
//            return new ApiResponse("The student's account has been successfully confirmed.");
//        } else {
//            return new ApiResponse("Invalid confirmation token.");
//        }
//    }

    @GetMapping("/confirm")
    public Object confirmEmail(@RequestParam("token") String token) {
        boolean isVerified = studentService.confirmEmail(token);
        if (isVerified) {
            return new RedirectView("/set-password.html?token=" + token, true, true, false);
        } else {
            return new ApiResponse("Invalid confirmation token.");
        }
    }
    
    @PostMapping("/set-password")
    public ApiResponse setPassword(@RequestParam("token") String token,
                                   @RequestParam("password") String password,
                                   @RequestParam("confirmPassword") String confirmPassword) {
        boolean success = studentService.setPassword(token, password, confirmPassword);
        if (success) {
            return new ApiResponse("Password set successfully");
        } else {
            return new ApiResponse("Failed to set password");
        }
    }
    
    
    @DeleteMapping("/delete")
    @ResponseBody
    public void deleteById(@RequestParam int id) {
        studentService.deleteById(id);
    }
    
    @DeleteMapping("deleteByIndexNumber")
    @ResponseBody
    public void deleteByIndexNumber(@RequestParam int indexNumber) {
        studentService.deleteByIndexNumer(indexNumber);
    }

}

以及我的安全配置:

package pl.studia.university.configuration;


@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf.disable())
                .authorizeHttpRequests(auth -> auth

//                        // Allow access to the set-password page and the confirm endpoint without authentication
//                        .requestMatchers("/set-password.html", "/api/v1/students/confirm", "/style.css").permitAll()
//                        // Make sure other endpoints are authenticated properly
//                        .requestMatchers("/api/v1/students").hasRole("ADMIN")
//                        .requestMatchers("/api/v1/students/create").hasAuthority("ROLE_ADMIN")
//                        .requestMatchers("/api/v1/students/delete").hasRole("ADMIN")
//                        .requestMatchers("/api/v1/students/deleteByIndexNumber").hasRole("ADMIN")
//                        .anyRequest().authenticated()
.requestMatchers("/api/v1/students/set-password.html", "/set-password", "/api/v1/students/confirm", "/login.html", "/style.css", "/js/**", "/images/**").permitAll()  
.anyRequest().authenticated()
)
.formLogin(form -\> form
.loginPage("/login.html")
.loginProcessingUrl("/perform_login")
.defaultSuccessUrl("/", true)
.failureUrl("/login?error=true")
.permitAll()
)
.logout(logout -\> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout=true")
.permitAll()
)
.httpBasic(withDefaults());

        return http.build();
    }
    
    @Bean
    public UserDetailsService users(PasswordEncoder passwordEncoder) {
        UserDetails admin = User.withUsername("admin")
                .password(passwordEncoder.encode("admin"))
                .roles("ADMIN", "USER")
                .build();
    
        UserDetails user = User.withUsername("user")
                .password(passwordEncoder.encode("user"))
                .roles("USER")
                .build();
    
        return new InMemoryUserDetailsManager(user, admin);
    }
    
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}

将 requestMatchers 从 /api/v1/students/set-password.html 更改为 /set-password.html

spring-security
1个回答
0
投票

.requestMatchers("/api/v1/students/set-password.html", "/set-password").permitAll()

看起来您错误地指定了restapi和html的路径。尝试将其更改为

.requestMatchers("/api/v1/students/set-password", "/set-password.html").permitAll() 
© www.soinside.com 2019 - 2024. All rights reserved.