diff --git a/pom.xml b/pom.xml index f2a24b7..8660950 100644 --- a/pom.xml +++ b/pom.xml @@ -138,6 +138,11 @@ commons-io 2.11.0 + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + 2.20.1 + org.springframework.boot diff --git a/src/main/java/com/example/dateplanner/configurations/SecurityConfig.java b/src/main/java/com/example/dateplanner/configurations/SecurityConfig.java index f055268..068f815 100644 --- a/src/main/java/com/example/dateplanner/configurations/SecurityConfig.java +++ b/src/main/java/com/example/dateplanner/configurations/SecurityConfig.java @@ -12,16 +12,10 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; -import org.springframework.security.authentication.ReactiveAuthenticationManager; -import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager; -import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.config.web.server.SecurityWebFiltersOrder; import org.springframework.security.config.web.server.ServerHttpSecurity; -import org.springframework.security.core.userdetails.ReactiveUserDetailsPasswordService; -import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.server.SecurityWebFilterChain; @@ -30,8 +24,7 @@ import org.springframework.security.web.server.csrf.CookieServerCsrfTokenReposit import org.springframework.security.web.server.csrf.ServerCsrfTokenRequestAttributeHandler; import org.springframework.security.web.server.savedrequest.ServerRequestCache; import org.springframework.security.web.server.savedrequest.WebSessionServerRequestCache; -import org.springframework.security.web.server.util.matcher.PathPatternParserServerWebExchangeMatcher; -import reactor.core.publisher.Mono; + import java.net.URI; @Slf4j @@ -40,31 +33,10 @@ import java.net.URI; @RequiredArgsConstructor @EnableReactiveMethodSecurity public class SecurityConfig { - private final AppUserRepository userRepository; private final JwtService jwtService; - - // Цепочка для API (Basic Auth) - CSRF отключаем @Bean - @Order(1) - public SecurityWebFilterChain apiFilterChain(ServerHttpSecurity http) { - return http - .securityMatcher(new PathPatternParserServerWebExchangeMatcher("/api/**")) - .authorizeExchange(exchange -> exchange - .pathMatchers("/api/mobile/login").permitAll() - .anyExchange().authenticated() - ) - .httpBasic(Customizer.withDefaults()) - .formLogin(ServerHttpSecurity.FormLoginSpec::disable) - .csrf(ServerHttpSecurity.CsrfSpec::disable) // CSRF отключаем для API - .authenticationManager(reactiveAuthenticationManager()) - .build(); - } - - // Цепочка для веб-интерфейса (Form Login) - CSRF включаем - @Bean - @Order(2) - public SecurityWebFilterChain webFilterChain(ServerHttpSecurity http) { + public SecurityWebFilterChain filterChain(ServerHttpSecurity http){ ServerCsrfTokenRequestAttributeHandler requestHandler = new ServerCsrfTokenRequestAttributeHandler(); requestHandler.setTokenFromMultipartDataEnabled(true); @@ -74,13 +46,13 @@ public class SecurityConfig { ErrorHandlingFilter errorHandlingFilter = new ErrorHandlingFilter(); return http - .securityMatcher(new PathPatternParserServerWebExchangeMatcher("/account/**")) .csrf(csrf -> csrf.csrfTokenRequestHandler(requestHandler).csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse())) .addFilterAt(authenticationWebFilter, SecurityWebFiltersOrder.AUTHENTICATION) - .addFilterAfter(errorHandlingFilter, SecurityWebFiltersOrder.AUTHENTICATION) + //.addFilterAfter(errorHandlingFilter, SecurityWebFiltersOrder.AUTHENTICATION) .authorizeExchange(exchange -> exchange - .pathMatchers("/account/login").permitAll() - .anyExchange().authenticated() + .pathMatchers("/account/login","/error","/error/**").permitAll() + .pathMatchers("/account/**").authenticated() + .anyExchange().permitAll() ) .formLogin(loginSpec -> loginSpec.loginPage("/account/login").authenticationSuccessHandler(authenticationSuccessHandler())) .logout(logoutSpec -> logoutSpec.logoutSuccessHandler(logoutSuccessHandler())) @@ -88,19 +60,6 @@ public class SecurityConfig { .build(); } - // Цепочка для всех остальных путей (публичные) - @Bean - @Order(3) - public SecurityWebFilterChain defaultFilterChain(ServerHttpSecurity http) { - return http - .securityMatcher(new PathPatternParserServerWebExchangeMatcher("/**")) - .authorizeExchange(exchange -> exchange - .anyExchange().permitAll() - ) - .csrf(ServerHttpSecurity.CsrfSpec::disable) - .build(); - } - @Bean public ServerRequestCache serverRequestCache() { return new WebSessionServerRequestCache(); @@ -129,33 +88,12 @@ public class SecurityConfig { } @Bean - public ReactiveAuthenticationManager reactiveAuthenticationManager() { - UserDetailsRepositoryReactiveAuthenticationManager manager = new UserDetailsRepositoryReactiveAuthenticationManager(userService()); - manager.setPasswordEncoder(passwordEncoder()); - manager.setUserDetailsPasswordService(userDetailsPasswordService()); - return manager; - } - - @Bean - public ReactiveUserDetailsPasswordService userDetailsPasswordService() { - return new ReactiveUserDetailsPasswordService() { - @Override - public Mono updatePassword(UserDetails user, String newPassword) { - return userRepository.findByPhone(user.getUsername()).flatMap(appUser -> { - appUser.setPassword(passwordEncoder().encode(newPassword)); - return userRepository.save(appUser); - }); - } - }; + public PasswordEncoder passwordEncoder(){ + return new BCryptPasswordEncoder(); } @Bean public UserService userService(){ return new UserService(userRepository,passwordEncoder()); } - - @Bean - public PasswordEncoder passwordEncoder(){ - return new BCryptPasswordEncoder(); - } } diff --git a/src/main/java/com/example/dateplanner/configurations/handlers/JwtAuthenticationManager.java b/src/main/java/com/example/dateplanner/configurations/handlers/JwtAuthenticationManager.java index f45208e..28602a2 100644 --- a/src/main/java/com/example/dateplanner/configurations/handlers/JwtAuthenticationManager.java +++ b/src/main/java/com/example/dateplanner/configurations/handlers/JwtAuthenticationManager.java @@ -29,7 +29,6 @@ public class JwtAuthenticationManager implements ReactiveAuthenticationManager { //log.info("start auth manager"); String accessToken = authentication.getPrincipal().toString(); String refreshToken = authentication.getCredentials().toString(); - log.info("refresh is {},{}", accessToken, refreshToken); if(jwt.validateToken(accessToken)){ //log.info("access token is valid"); @@ -105,7 +104,7 @@ public class JwtAuthenticationManager implements ReactiveAuthenticationManager { } private Mono baseAuth(Authentication authentication){ - log.info("access and refresh token is not valid - try authenticate by basic login"); + //log.info("access and refresh token is not valid - try authenticate by basic login"); String username = authentication.getPrincipal().toString(); String password = authentication.getCredentials().toString(); return userService.findByUsername(username).flatMap(user -> { diff --git a/src/main/java/com/example/dateplanner/configurations/handlers/JwtAuthenticationSuccessHandler.java b/src/main/java/com/example/dateplanner/configurations/handlers/JwtAuthenticationSuccessHandler.java index 3d4b82e..437dbb0 100644 --- a/src/main/java/com/example/dateplanner/configurations/handlers/JwtAuthenticationSuccessHandler.java +++ b/src/main/java/com/example/dateplanner/configurations/handlers/JwtAuthenticationSuccessHandler.java @@ -53,4 +53,4 @@ public class JwtAuthenticationSuccessHandler implements ServerAuthenticationSucc return webFilterExchange.getExchange().getResponse().setComplete(); }); } -} +} \ No newline at end of file diff --git a/src/main/java/com/example/dateplanner/models/entities/AppUser.java b/src/main/java/com/example/dateplanner/models/entities/AppUser.java index 9bdcebd..2627ed2 100644 --- a/src/main/java/com/example/dateplanner/models/entities/AppUser.java +++ b/src/main/java/com/example/dateplanner/models/entities/AppUser.java @@ -48,7 +48,7 @@ public class AppUser implements UserDetails { @Override public String getUsername() { - return this.phone; + return getPhone(); } @Override diff --git a/src/main/java/com/example/dateplanner/repositories/AppUserRepository.java b/src/main/java/com/example/dateplanner/repositories/AppUserRepository.java index 4c1750a..6615582 100644 --- a/src/main/java/com/example/dateplanner/repositories/AppUserRepository.java +++ b/src/main/java/com/example/dateplanner/repositories/AppUserRepository.java @@ -9,4 +9,5 @@ import java.util.UUID; public interface AppUserRepository extends R2dbcRepository { Mono findByPhone(String phone); + Mono findByUsername(String username); } diff --git a/src/main/java/com/example/dateplanner/services/UserService.java b/src/main/java/com/example/dateplanner/services/UserService.java index 9fd2ff5..a21129c 100644 --- a/src/main/java/com/example/dateplanner/services/UserService.java +++ b/src/main/java/com/example/dateplanner/services/UserService.java @@ -2,20 +2,22 @@ package com.example.dateplanner.services; import com.example.dateplanner.repositories.AppUserRepository; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.userdetails.ReactiveUserDetailsService; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import reactor.core.publisher.Mono; -@Service +@Slf4j @RequiredArgsConstructor public class UserService implements ReactiveUserDetailsService { - private final AppUserRepository appUserRepository; + private final AppUserRepository userRepository; private final PasswordEncoder passwordEncoder; @Override public Mono findByUsername(String username) { - return appUserRepository.findByPhone(username).flatMap(Mono::just).cast(UserDetails.class); + log.info("username {}", username); + return userRepository.findByPhone(username).flatMap(Mono::just).cast(UserDetails.class); } } diff --git a/src/main/java/com/example/dateplanner/utils/CookieUtil.java b/src/main/java/com/example/dateplanner/utils/CookieUtil.java index bef4e9f..9634f8e 100644 --- a/src/main/java/com/example/dateplanner/utils/CookieUtil.java +++ b/src/main/java/com/example/dateplanner/utils/CookieUtil.java @@ -11,7 +11,7 @@ public class CookieUtil { private final String SESSION; protected CookieUtil(){ - String appName = "pstweb"; + String appName = "dp"; REFRESH = appName + "-refresh"; ACCESS = appName + "-access"; SESSION = appName + "-session"; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index b43845b..eff447a 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -23,7 +23,7 @@ spring.flyway.locations=db/migration spring.flyway.validate-migration-naming=true spring.flyway.baseline-on-migrate=true #====================== minio configuration ===================== -minio.bucket= +minio.bucket=${spring.application.name} minio.url= minio.cdn= minio.username= diff --git a/src/main/resources/static/js/site/blocks/header.js b/src/main/resources/static/js/site/blocks/header.js index f72517b..1f03f9a 100644 --- a/src/main/resources/static/js/site/blocks/header.js +++ b/src/main/resources/static/js/site/blocks/header.js @@ -103,13 +103,14 @@ function initHeader($header){
+
- +
- +