Ошибка загрузки Spring 403 при отправке запроса

#java #angular #spring #spring-boot #spring-security

#java #угловой #весна #spring-boot #spring-безопасность

Вопрос:

Моя система состоит из 3 частей. Приложение Spring Boot, приложение Angular и приложение для Android. Когда мое приложение для Android отправляет запрос на сброс пароля (если вы его не помните), приложение Spring Boot получает этот запрос с помощью этого метода:

 @PostMapping("/forgot_password")
public String processForgotPassword(@RequestBody String email, HttpServletRequest request) {
    try {
        String token = RandomString.make(30);
        userService.updateResetPasswordToken(token, email);
        String resetPasswordLink = "https://jakuwegiel.web.app/projects/endless-blow/reset-password?token="   token;
        sendEmail(email, resetPasswordLink);

    } catch (Exception ex) {
        System.out.println(ex.getMessage());
    }
    return "Email has been sent";
}
 

где updateResetPasswordToken() :

 public void updateResetPasswordToken(String token, String email) throws SQLException {
    UserDetails userDetails = usersDao.getUserDetailsByEmail(connFromUserService, email);
    if (userDetails != null) {
        User user = usersDao.getUserByName(connFromUserService, userDetails.getName());
        usersDao.setResetPasswordToken(connFromUserService, user, token);
    }
}
 

где getUserDetailsByEmail() :

 public UserDetails getUserDetailsByEmail(Connection connection, String email) {
    UserDetails userDetails = new UserDetails();
    PreparedStatement ps;
    try {
        ps = connection.prepareStatement("SELECT * from users_details where email = '" email "'");
        ResultSet rs = ps.executeQuery();
        if (rs.next()) {
            userDetails = new UserDetails(rs.getString(2), rs.getString(3));
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return userDetails;
}
 

и getUserByName() это:

 public User getUserByName(Connection connection, String name) throws SQLException {
    User user = new User();
    PreparedStatement ps;
    try {
        ps = connection.prepareStatement("SELECT * from users where username = '" name "'");
        ResultSet rs = ps.executeQuery();
        if (rs.next()) {
            user = new User(rs.getString(2), rs.getString(3));
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return user;
}
 

и setResetPasswordToken() это:

 public void setResetPasswordToken(Connection connection, User user, String token) {
    PreparedStatement ps;
    try {
        ps = connection.prepareStatement("UPDATE users set reset_password_token = '"   token   "' where username = '"   user.getUsername()   "'");
        ps.executeUpdate();
    } catch (SQLException e) {
        System.out.println(e.getMessage());
    }
}
 

Затем пользователь получает ссылку сброса по электронной почте. Он открывает ссылку, которая открывает приложение Angular, и я дважды ввожу в два поля EditText passsword и отправляю с помощью кнопки отправить, которая выполняет этот код:

   public postResetPassword(token: string, password: string): Observable<any> {
    const body = {
      'token': token,
      'password': password
    };
    const headers = new HttpHeaders().set('Content-Type', 'application/json; charset=utf-8');
    return this.http.post<any>('https://endlessblow-1.herokuapp.com/reset_password', body,{headers: headers});
  }
 

Что странно, что этот код Angular генерирует запрос ПАРАМЕТРОВ, а не POST почему?
Приложение Spring Boot получает этот запрос с помощью метода:

 @RequestMapping(value = "/reset_password", consumes="application/json", method = {RequestMethod.OPTIONS, RequestMethod.POST, RequestMethod.GET})
public String processResetPassword(@RequestBody TokenAndPassword tokenAndPassword) {
    try {
        User user = userService.getByResetPasswordToken(tokenAndPassword.getToken());
        if (user == null) {
            return "message1";
        } else {
            userService.updatePassword(user, tokenAndPassword.getPassword());
            System.out.println("You have successfully changed your password.");
        }
    }
    catch (Exception ex) {
        System.out.println(ex.getMessage());
        return "Error. Did you use your token already? Or does this link come from email?";
    }

    return "You have successfully changed your password.";
}
 

Но, наконец, каждый раз, когда появляется /reset_password, появляется ОШИБКА 403.

Я также добавил такой класс:

 @Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
public void configure(HttpSecurity http) throws Exception {
    http
            .csrf().disable()
            .authorizeRequests().anyRequest().permitAll();
}
}
 

но это ничего не дает.

Что не так с этим кодом?

Большое, очень большое спасибо за помощь!

Ответ №1:

Проблема, скорее всего, связана с предполетным запросом, который отправляет приложение angular. Вы можете отключить cors, добавив это в свою конфигурацию безопасности:

 @Override
public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**").allowedMethods("*");
}
 

или вы можете настроить его в соответствии с вашим вариантом использования, следуя примеру из документации spring https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-cors-global-java

Комментарии:

1. Хорошо, завтра я это проверю. Пожалуйста, следите за обновлениями в этой теме, хорошо? Если окажется, что это работает, я все равно отмечу этот ответ как принятый, пока вы оставляете лайк 🙂