From 5488a07b6f2848cec4df1357ebb7535d8df29465 Mon Sep 17 00:00:00 2001 From: Uladzimir Date: Fri, 28 Feb 2025 19:45:09 +0300 Subject: [PATCH] 2024-11 spring-23-auth --- .../spring/controller/PagesController.java | 11 +-- .../security/SecurityConfiguration.java | 4 +- 2024-11/spring-23/pom.xml | 69 ++++++++++++++++++ .../src/main/java/ru/otus/spring/Main.java | 13 ++++ .../spring/controller/PagesController.java | 54 ++++++++++++++ .../ru/otus/spring/security/AnonimusUD.java | 45 ++++++++++++ .../security/SecurityConfiguration.java | 70 +++++++++++++++++++ .../spring/security/filter/MyOwnFilter.java | 30 ++++++++ .../src/main/resources/application.yml | 4 ++ .../resources/templates/authenticated.html | 10 +++ .../src/main/resources/templates/error.html | 11 +++ .../src/main/resources/templates/index.html | 12 ++++ .../src/main/resources/templates/public.html | 10 +++ .../src/main/resources/templates/success.html | 10 +++ .../controller/PagesControllerTest.java | 33 +++++++++ 15 files changed, 378 insertions(+), 8 deletions(-) create mode 100644 2024-11/spring-23/pom.xml create mode 100644 2024-11/spring-23/src/main/java/ru/otus/spring/Main.java create mode 100644 2024-11/spring-23/src/main/java/ru/otus/spring/controller/PagesController.java create mode 100644 2024-11/spring-23/src/main/java/ru/otus/spring/security/AnonimusUD.java create mode 100644 2024-11/spring-23/src/main/java/ru/otus/spring/security/SecurityConfiguration.java create mode 100644 2024-11/spring-23/src/main/java/ru/otus/spring/security/filter/MyOwnFilter.java create mode 100644 2024-11/spring-23/src/main/resources/application.yml create mode 100644 2024-11/spring-23/src/main/resources/templates/authenticated.html create mode 100644 2024-11/spring-23/src/main/resources/templates/error.html create mode 100644 2024-11/spring-23/src/main/resources/templates/index.html create mode 100644 2024-11/spring-23/src/main/resources/templates/public.html create mode 100644 2024-11/spring-23/src/main/resources/templates/success.html create mode 100644 2024-11/spring-23/src/test/java/ru/otus/spring/controller/PagesControllerTest.java diff --git a/2024-09/spring-23/src/main/java/ru/otus/spring/controller/PagesController.java b/2024-09/spring-23/src/main/java/ru/otus/spring/controller/PagesController.java index dc70c3b4..ed86a8c5 100644 --- a/2024-09/spring-23/src/main/java/ru/otus/spring/controller/PagesController.java +++ b/2024-09/spring-23/src/main/java/ru/otus/spring/controller/PagesController.java @@ -1,5 +1,6 @@ package ru.otus.spring.controller; +import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.User; @@ -18,11 +19,11 @@ public class PagesController { } @GetMapping("/public") - public String publicPage(/*@RequestParam(name = "SpecialValue") String specialValue, Model model*/) { -// model.addAttribute("secret", specialValue); -// SecurityContext securityContext = SecurityContextHolder.getContext(); -// Authentication authentication = securityContext.getAuthentication(); -// System.out.println(authentication.getPrincipal()); + public String publicPage(@RequestParam(name = "SpecialValue") String specialValue, Model model) { + model.addAttribute("secret", specialValue); +/* SecurityContext securityContext = SecurityContextHolder.getContext(); + Authentication authentication = securityContext.getAuthentication(); + System.out.println(authentication.getPrincipal());*/ return "public"; } diff --git a/2024-09/spring-23/src/main/java/ru/otus/spring/security/SecurityConfiguration.java b/2024-09/spring-23/src/main/java/ru/otus/spring/security/SecurityConfiguration.java index 432d16b7..b4e50728 100644 --- a/2024-09/spring-23/src/main/java/ru/otus/spring/security/SecurityConfiguration.java +++ b/2024-09/spring-23/src/main/java/ru/otus/spring/security/SecurityConfiguration.java @@ -36,7 +36,7 @@ public class SecurityConfiguration { .anyRequest().permitAll() ) // .anonymous(a -> a.principal(new AnonimusUD()).authorities("ROLE_ANONYMOUS")) -// .addFilterAfter(new MyOwnFilter(), AuthorizationFilter.class) + .addFilterAfter(new MyOwnFilter(), AuthorizationFilter.class) // .httpBasic(Customizer.withDefaults()) .formLogin(Customizer.withDefaults()) /* @@ -44,10 +44,8 @@ public class SecurityConfiguration { .failureForwardUrl("/fail") ) */ -/* .rememberMe(rm -> rm.key("AnyKey") .tokenValiditySeconds(600)) -*/ ; return http.build(); } diff --git a/2024-11/spring-23/pom.xml b/2024-11/spring-23/pom.xml new file mode 100644 index 00000000..5d73fcd5 --- /dev/null +++ b/2024-11/spring-23/pom.xml @@ -0,0 +1,69 @@ + + + 4.0.0 + + ru.otus + classwork + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 3.3.6 + + + + UTF-8 + UTF-8 + 17 + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + + org.springframework.boot + spring-boot-starter-security + + + + + org.springframework.boot + spring-boot-starter-test + + + + org.springframework.security + spring-security-test + ${spring-security.version} + + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/2024-11/spring-23/src/main/java/ru/otus/spring/Main.java b/2024-11/spring-23/src/main/java/ru/otus/spring/Main.java new file mode 100644 index 00000000..e8fdc91d --- /dev/null +++ b/2024-11/spring-23/src/main/java/ru/otus/spring/Main.java @@ -0,0 +1,13 @@ +package ru.otus.spring; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Main { + + public static void main(String[] args) { + SpringApplication.run(Main.class); + // http://localhost:8080/ + } +} diff --git a/2024-11/spring-23/src/main/java/ru/otus/spring/controller/PagesController.java b/2024-11/spring-23/src/main/java/ru/otus/spring/controller/PagesController.java new file mode 100644 index 00000000..ed86a8c5 --- /dev/null +++ b/2024-11/spring-23/src/main/java/ru/otus/spring/controller/PagesController.java @@ -0,0 +1,54 @@ +package ru.otus.spring.controller; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@Controller +public class PagesController { + + @GetMapping("/") + public String indexPage() { + return "index"; + } + + @GetMapping("/public") + public String publicPage(@RequestParam(name = "SpecialValue") String specialValue, Model model) { + model.addAttribute("secret", specialValue); +/* SecurityContext securityContext = SecurityContextHolder.getContext(); + Authentication authentication = securityContext.getAuthentication(); + System.out.println(authentication.getPrincipal());*/ + return "public"; + } + + @GetMapping("/authenticated") + public String authenticatedPage(Model model) { + SecurityContext securityContext = SecurityContextHolder.getContext(); + User user = (User) securityContext.getAuthentication().getPrincipal(); + model.addAttribute("userName", user.getUsername()); + return "authenticated"; + } + + @GetMapping("/success") + public String successPage() { + return "success"; + } + + @GetMapping("/error") + public String errorPage(Model model) { + model.addAttribute("source", "errorPage"); + return "error"; + } + + @PostMapping("/fail") + public String failPage(Model model) { + model.addAttribute("source", "failPage"); + return "error"; + } +} diff --git a/2024-11/spring-23/src/main/java/ru/otus/spring/security/AnonimusUD.java b/2024-11/spring-23/src/main/java/ru/otus/spring/security/AnonimusUD.java new file mode 100644 index 00000000..bf2a2210 --- /dev/null +++ b/2024-11/spring-23/src/main/java/ru/otus/spring/security/AnonimusUD.java @@ -0,0 +1,45 @@ +package ru.otus.spring.security; + +import lombok.Data; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; + +@Data +public class AnonimusUD implements UserDetails { + @Override + public Collection getAuthorities() { + return null; + } + + @Override + public String getPassword() { + return null; + } + + @Override + public String getUsername() { + return "anonymous"; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } +} diff --git a/2024-11/spring-23/src/main/java/ru/otus/spring/security/SecurityConfiguration.java b/2024-11/spring-23/src/main/java/ru/otus/spring/security/SecurityConfiguration.java new file mode 100644 index 00000000..b4e50728 --- /dev/null +++ b/2024-11/spring-23/src/main/java/ru/otus/spring/security/SecurityConfiguration.java @@ -0,0 +1,70 @@ +package ru.otus.spring.security; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.crypto.password.NoOpPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.access.intercept.AuthorizationFilter; +import ru.otus.spring.security.filter.MyOwnFilter; + +import java.util.ArrayList; + +@EnableWebSecurity +@Configuration +public class SecurityConfiguration { + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) + throws Exception { + http + .csrf(AbstractHttpConfigurer::disable) + .sessionManagement((session) -> session + .sessionCreationPolicy(SessionCreationPolicy.ALWAYS)) + .authorizeHttpRequests((authorize) -> authorize + .requestMatchers("/").permitAll() + .requestMatchers("/public").permitAll() + .requestMatchers("/authenticated", "/success").authenticated() + .anyRequest().permitAll() + ) +// .anonymous(a -> a.principal(new AnonimusUD()).authorities("ROLE_ANONYMOUS")) + .addFilterAfter(new MyOwnFilter(), AuthorizationFilter.class) +// .httpBasic(Customizer.withDefaults()) + .formLogin(Customizer.withDefaults()) +/* + .formLogin(fm -> fm.defaultSuccessUrl("/success") + .failureForwardUrl("/fail") + ) +*/ + .rememberMe(rm -> rm.key("AnyKey") + .tokenValiditySeconds(600)) + ; + return http.build(); + } + + @SuppressWarnings("deprecation") + @Bean + public PasswordEncoder passwordEncoder() { + return NoOpPasswordEncoder.getInstance(); + } + + @Bean + public InMemoryUserDetailsManager userDetailsService() { + UserDetails user = User + .builder() + .username("user") + .password("password") + .roles("USER") + .build(); + return new InMemoryUserDetailsManager(user); + + } +} diff --git a/2024-11/spring-23/src/main/java/ru/otus/spring/security/filter/MyOwnFilter.java b/2024-11/spring-23/src/main/java/ru/otus/spring/security/filter/MyOwnFilter.java new file mode 100644 index 00000000..2b81609f --- /dev/null +++ b/2024-11/spring-23/src/main/java/ru/otus/spring/security/filter/MyOwnFilter.java @@ -0,0 +1,30 @@ +package ru.otus.spring.security.filter; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; +import org.springframework.web.filter.GenericFilterBean; + +import java.io.IOException; + +public class MyOwnFilter extends GenericFilterBean { + @Override + public void doFilter(ServletRequest servletRequest, + ServletResponse servletResponse, + FilterChain filterChain) throws IOException, ServletException { + var requestWrapper = new HttpServletRequestWrapper((HttpServletRequest) servletRequest) { + @Override + public String[] getParameterValues(String name) { + if ("SpecialValue".equals(name)) { + return new String[]{"My dirty secret"}; + } + return super.getParameterValues(name); + } + }; + + filterChain.doFilter(requestWrapper, servletResponse); + } +} diff --git a/2024-11/spring-23/src/main/resources/application.yml b/2024-11/spring-23/src/main/resources/application.yml new file mode 100644 index 00000000..d07e4971 --- /dev/null +++ b/2024-11/spring-23/src/main/resources/application.yml @@ -0,0 +1,4 @@ +logging: + level: + root: error + org.springframework: info \ No newline at end of file diff --git a/2024-11/spring-23/src/main/resources/templates/authenticated.html b/2024-11/spring-23/src/main/resources/templates/authenticated.html new file mode 100644 index 00000000..62f1eb0d --- /dev/null +++ b/2024-11/spring-23/src/main/resources/templates/authenticated.html @@ -0,0 +1,10 @@ + + + + + Только для авторизованных + + +Только для авторизованных. Вы как раз такой) + + diff --git a/2024-11/spring-23/src/main/resources/templates/error.html b/2024-11/spring-23/src/main/resources/templates/error.html new file mode 100644 index 00000000..41a3f8e2 --- /dev/null +++ b/2024-11/spring-23/src/main/resources/templates/error.html @@ -0,0 +1,11 @@ + + + + + Упс... + + +Что-то пошло не так. Печалька
+Источник: Неизвестен + + diff --git a/2024-11/spring-23/src/main/resources/templates/index.html b/2024-11/spring-23/src/main/resources/templates/index.html new file mode 100644 index 00000000..f2d1d1ae --- /dev/null +++ b/2024-11/spring-23/src/main/resources/templates/index.html @@ -0,0 +1,12 @@ + + + + + Главная страница + + +/public +
+/authenticated + + diff --git a/2024-11/spring-23/src/main/resources/templates/public.html b/2024-11/spring-23/src/main/resources/templates/public.html new file mode 100644 index 00000000..58fca813 --- /dev/null +++ b/2024-11/spring-23/src/main/resources/templates/public.html @@ -0,0 +1,10 @@ + + + + + Доступен всем + + +Доступен всем, но есть секрет: Нет секрета + + diff --git a/2024-11/spring-23/src/main/resources/templates/success.html b/2024-11/spring-23/src/main/resources/templates/success.html new file mode 100644 index 00000000..58414c01 --- /dev/null +++ b/2024-11/spring-23/src/main/resources/templates/success.html @@ -0,0 +1,10 @@ + + + + + Вы успешно вошли ! + + +Вы успешно вошли ! + + diff --git a/2024-11/spring-23/src/test/java/ru/otus/spring/controller/PagesControllerTest.java b/2024-11/spring-23/src/test/java/ru/otus/spring/controller/PagesControllerTest.java new file mode 100644 index 00000000..847927b3 --- /dev/null +++ b/2024-11/spring-23/src/test/java/ru/otus/spring/controller/PagesControllerTest.java @@ -0,0 +1,33 @@ +package ru.otus.spring.controller; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.context.annotation.Import; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.web.servlet.MockMvc; +import ru.otus.spring.security.SecurityConfiguration; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(PagesController.class) +@Import(SecurityConfiguration.class) +public class PagesControllerTest { + + @Autowired + private MockMvc mockMvc; + +/* @WithMockUser( + username = "admin", + authorities = {"ROLE_ADMIN"} + )*/ + @Test + public void testAuthenticatedOnAdmin() throws Exception { + mockMvc.perform(get("/authenticated") + .with(user("admin").authorities(new SimpleGrantedAuthority("ROLE_ADMIN")))) + .andExpect(status().isOk()); + } +}