2026-01 spring-ss-auth

This commit is contained in:
VladimirMagerov
2026-04-22 19:24:39 +03:00
parent f09cbbfdc9
commit 6277f8c976
13 changed files with 367 additions and 0 deletions
+69
View File
@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ru.otus</groupId>
<artifactId>classwork</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.6</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring MVC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- For Spring Security testing -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>${spring-security.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -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/
}
}
@@ -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";
}
}
@@ -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<? extends GrantedAuthority> 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;
}
}
@@ -0,0 +1,66 @@
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().authenticated()
)
// .anonymous(a -> a.principal(new AnonimusUD()).authorities("ROLE_ANONYMOUS"))
.addFilterAfter(new MyOwnFilter(), AuthorizationFilter.class)
// .httpBasic(Customizer.withDefaults())
// .formLogin(Customizer.withDefaults())
.formLogin(fm ->fm.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);
}
}
@@ -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);
}
}
@@ -0,0 +1,4 @@
logging:
level:
root: error
org.springframework: info
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8"/>
<title>Только для авторизованных</title>
</head>
<body>
Только для авторизованных. Вы <span th:text = "${userName}"></span> как раз такой)
</body>
</html>
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8"/>
<title>Упс...</title>
</head>
<body>
Что-то пошло не так. Печалька <br/>
Источник: <span th:text = "${source}">Неизвестен</span>
</body>
</html>
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>Главная страница</title>
</head>
<body>
<a th:href="@{public}">/public</a>
<br>
<a th:href="@{authenticated}">/authenticated</a>
</body>
</html>
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8"/>
<title>Доступен всем</title>
</head>
<body>
Доступен всем, но есть секрет: <span th:text = "${secret}">Нет секрета</span>
</body>
</html>
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Вы успешно вошли !</title>
</head>
<body>
Вы успешно вошли !
</body>
</html>
@@ -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());
}
}