From e3dd4db68e71dede271609df742eca744ec37860 Mon Sep 17 00:00:00 2001 From: kataus Date: Fri, 10 Mar 2023 19:55:29 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D1=80=D0=B8=D0=BC=D0=B5=D1=80=D1=8B=20?= =?UTF-8?q?=D0=BA=20=D0=B7=D0=B0=D0=BD=D1=8F=D1=82=D0=B8=D1=8E=20=D0=BF?= =?UTF-8?q?=D0=BE=20=D0=B0=D0=B2=D1=82=D0=BE=D1=80=D0=B8=D0=B7=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2022-11/spring-26/ACL/pom.xml | 83 +++++++++++++++++++ .../src/main/java/ru/otus/spring/Main.java | 14 ++++ .../ru/otus/spring/model/NoticeMessage.java | 33 ++++++++ .../main/java/ru/otus/spring/model/Pack.java | 4 + .../repository/NoticeMessageRepository.java | 25 ++++++ .../spring/rest/NoticeMessageController.java | 35 ++++++++ .../ru/otus/spring/security/AclConfig.java | 79 ++++++++++++++++++ .../AclMethodSecurityConfiguration.java | 22 +++++ .../security/SecurityConfiguration.java | 42 ++++++++++ .../ru/otus/spring/service/NoticeService.java | 42 ++++++++++ .../ACL/src/main/resources/application.yml | 13 +++ .../spring-26/ACL/src/main/resources/data.sql | 28 +++++++ .../ACL/src/main/resources/schema.sql | 58 +++++++++++++ .../src/main/resources/templates/error.html | 9 ++ .../src/main/resources/templates/index.html | 15 ++++ 2022-11/spring-26/classwork/pom.xml | 54 ++++++++++++ .../spring/SpringSecurityAuthorization.java | 13 +++ .../spring/controller/PagesController.java | 59 +++++++++++++ .../controller/SecurityControllerAdvice.java | 16 ++++ .../security/MethodSecurityConfiguration.java | 10 +++ .../security/SecurityConfiguration.java | 45 ++++++++++ .../ru/otus/spring/service/MyService.java | 17 ++++ .../src/main/resources/templates/admin.html | 9 ++ .../resources/templates/authenticated.html | 9 ++ .../src/main/resources/templates/error.html | 9 ++ .../src/main/resources/templates/index.html | 15 ++++ .../src/main/resources/templates/manager.html | 9 ++ .../src/main/resources/templates/public.html | 9 ++ .../src/main/resources/templates/success.html | 9 ++ .../src/main/resources/templates/user.html | 9 ++ 2022-11/spring-26/solution2/pom.xml | 54 ++++++++++++ .../spring/SpringSecurityAuthorization.java | 13 +++ .../spring/controller/PagesController.java | 56 +++++++++++++ .../security/MethodSecurityConfiguration.java | 7 ++ .../security/SecurityConfiguration.java | 51 ++++++++++++ .../ru/otus/spring/service/MyService.java | 12 +++ .../src/main/resources/templates/admin.html | 9 ++ .../resources/templates/authenticated.html | 9 ++ .../src/main/resources/templates/error.html | 9 ++ .../src/main/resources/templates/index.html | 17 ++++ .../src/main/resources/templates/manager.html | 9 ++ .../src/main/resources/templates/public.html | 9 ++ .../src/main/resources/templates/success.html | 9 ++ .../src/main/resources/templates/user.html | 9 ++ 44 files changed, 1067 insertions(+) create mode 100644 2022-11/spring-26/ACL/pom.xml create mode 100644 2022-11/spring-26/ACL/src/main/java/ru/otus/spring/Main.java create mode 100644 2022-11/spring-26/ACL/src/main/java/ru/otus/spring/model/NoticeMessage.java create mode 100644 2022-11/spring-26/ACL/src/main/java/ru/otus/spring/model/Pack.java create mode 100644 2022-11/spring-26/ACL/src/main/java/ru/otus/spring/repository/NoticeMessageRepository.java create mode 100644 2022-11/spring-26/ACL/src/main/java/ru/otus/spring/rest/NoticeMessageController.java create mode 100644 2022-11/spring-26/ACL/src/main/java/ru/otus/spring/security/AclConfig.java create mode 100644 2022-11/spring-26/ACL/src/main/java/ru/otus/spring/security/AclMethodSecurityConfiguration.java create mode 100644 2022-11/spring-26/ACL/src/main/java/ru/otus/spring/security/SecurityConfiguration.java create mode 100644 2022-11/spring-26/ACL/src/main/java/ru/otus/spring/service/NoticeService.java create mode 100644 2022-11/spring-26/ACL/src/main/resources/application.yml create mode 100644 2022-11/spring-26/ACL/src/main/resources/data.sql create mode 100644 2022-11/spring-26/ACL/src/main/resources/schema.sql create mode 100644 2022-11/spring-26/ACL/src/main/resources/templates/error.html create mode 100644 2022-11/spring-26/ACL/src/main/resources/templates/index.html create mode 100644 2022-11/spring-26/classwork/pom.xml create mode 100644 2022-11/spring-26/classwork/src/main/java/ru/otus/spring/SpringSecurityAuthorization.java create mode 100644 2022-11/spring-26/classwork/src/main/java/ru/otus/spring/controller/PagesController.java create mode 100644 2022-11/spring-26/classwork/src/main/java/ru/otus/spring/controller/SecurityControllerAdvice.java create mode 100644 2022-11/spring-26/classwork/src/main/java/ru/otus/spring/security/MethodSecurityConfiguration.java create mode 100644 2022-11/spring-26/classwork/src/main/java/ru/otus/spring/security/SecurityConfiguration.java create mode 100644 2022-11/spring-26/classwork/src/main/java/ru/otus/spring/service/MyService.java create mode 100644 2022-11/spring-26/classwork/src/main/resources/templates/admin.html create mode 100644 2022-11/spring-26/classwork/src/main/resources/templates/authenticated.html create mode 100644 2022-11/spring-26/classwork/src/main/resources/templates/error.html create mode 100644 2022-11/spring-26/classwork/src/main/resources/templates/index.html create mode 100644 2022-11/spring-26/classwork/src/main/resources/templates/manager.html create mode 100644 2022-11/spring-26/classwork/src/main/resources/templates/public.html create mode 100644 2022-11/spring-26/classwork/src/main/resources/templates/success.html create mode 100644 2022-11/spring-26/classwork/src/main/resources/templates/user.html create mode 100644 2022-11/spring-26/solution2/pom.xml create mode 100644 2022-11/spring-26/solution2/src/main/java/ru/otus/spring/SpringSecurityAuthorization.java create mode 100644 2022-11/spring-26/solution2/src/main/java/ru/otus/spring/controller/PagesController.java create mode 100644 2022-11/spring-26/solution2/src/main/java/ru/otus/spring/security/MethodSecurityConfiguration.java create mode 100644 2022-11/spring-26/solution2/src/main/java/ru/otus/spring/security/SecurityConfiguration.java create mode 100644 2022-11/spring-26/solution2/src/main/java/ru/otus/spring/service/MyService.java create mode 100644 2022-11/spring-26/solution2/src/main/resources/templates/admin.html create mode 100644 2022-11/spring-26/solution2/src/main/resources/templates/authenticated.html create mode 100644 2022-11/spring-26/solution2/src/main/resources/templates/error.html create mode 100644 2022-11/spring-26/solution2/src/main/resources/templates/index.html create mode 100644 2022-11/spring-26/solution2/src/main/resources/templates/manager.html create mode 100644 2022-11/spring-26/solution2/src/main/resources/templates/public.html create mode 100644 2022-11/spring-26/solution2/src/main/resources/templates/success.html create mode 100644 2022-11/spring-26/solution2/src/main/resources/templates/user.html diff --git a/2022-11/spring-26/ACL/pom.xml b/2022-11/spring-26/ACL/pom.xml new file mode 100644 index 00000000..2ba139f5 --- /dev/null +++ b/2022-11/spring-26/ACL/pom.xml @@ -0,0 +1,83 @@ + + + 4.0.0 + + ru.otus + spring-framework-26-acl + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 2.6.10 + + + + 2.6.11 + 3.0.0 + UTF-8 + UTF-8 + 11 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + org.springframework.boot + spring-boot-starter-security + + + + org.springframework.security + spring-security-acl + + + net.sf.ehcache + ehcache-core + ${ehcache-core.version} + jar + + + org.springframework + spring-context-support + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.h2database + h2 + + + + + + org.springdoc + springdoc-openapi-ui + 1.6.9 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/Main.java b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/Main.java new file mode 100644 index 00000000..baca49d5 --- /dev/null +++ b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/Main.java @@ -0,0 +1,14 @@ +package ru.otus.spring; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; + +@SpringBootApplication +public class Main { + + public static void main(String[] args) { + SpringApplication.run(Main.class); + } +} diff --git a/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/model/NoticeMessage.java b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/model/NoticeMessage.java new file mode 100644 index 00000000..21457970 --- /dev/null +++ b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/model/NoticeMessage.java @@ -0,0 +1,33 @@ +package ru.otus.spring.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "system_message") +public class NoticeMessage { + + @Id + @Column + private Integer id; + @Column + private String content; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +} diff --git a/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/model/Pack.java b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/model/Pack.java new file mode 100644 index 00000000..8498e0cc --- /dev/null +++ b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/model/Pack.java @@ -0,0 +1,4 @@ +package ru.otus.spring.model; + +public class Pack { +} diff --git a/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/repository/NoticeMessageRepository.java b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/repository/NoticeMessageRepository.java new file mode 100644 index 00000000..4588eb21 --- /dev/null +++ b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/repository/NoticeMessageRepository.java @@ -0,0 +1,25 @@ +package ru.otus.spring.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.repository.query.Param; +import org.springframework.security.access.prepost.PostAuthorize; +import org.springframework.security.access.prepost.PostFilter; +import org.springframework.security.access.prepost.PreAuthorize; +import ru.otus.spring.model.NoticeMessage; + +import java.util.List; +import java.util.Optional; + +public interface NoticeMessageRepository extends JpaRepository { + + @PostFilter("hasPermission(filterObject, 'READ')") + List findAll(); + + @PostAuthorize("hasPermission(returnObject, 'READ')") + NoticeMessage getById(Integer id); + + @SuppressWarnings("unchecked") + @PreAuthorize("hasPermission(#noticeMessage, 'WRITE')") + NoticeMessage save(@Param("noticeMessage") NoticeMessage noticeMessage); + +} diff --git a/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/rest/NoticeMessageController.java b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/rest/NoticeMessageController.java new file mode 100644 index 00000000..fbf59c52 --- /dev/null +++ b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/rest/NoticeMessageController.java @@ -0,0 +1,35 @@ +package ru.otus.spring.rest; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RestController; +import ru.otus.spring.model.NoticeMessage; +import ru.otus.spring.repository.NoticeMessageRepository; + +import java.util.List; + +@RestController +public class NoticeMessageController { + + private final NoticeMessageRepository repository; + + public NoticeMessageController(NoticeMessageRepository repository) { + this.repository = repository; + } + + @GetMapping("/message") + public List getAll() { + return repository.findAll(); + } + + @GetMapping("/message/{id}") + public NoticeMessage getById(@PathVariable("id") Integer id) { + return repository.getById(id); + } + + @PutMapping("/message") + public NoticeMessage getById(NoticeMessage message) { + return repository.save(message); + } +} diff --git a/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/security/AclConfig.java b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/security/AclConfig.java new file mode 100644 index 00000000..36d7376a --- /dev/null +++ b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/security/AclConfig.java @@ -0,0 +1,79 @@ +package ru.otus.spring.security; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.ehcache.EhCacheFactoryBean; +import org.springframework.cache.ehcache.EhCacheManagerFactoryBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; +import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; +import org.springframework.security.acls.AclPermissionCacheOptimizer; +import org.springframework.security.acls.AclPermissionEvaluator; +import org.springframework.security.acls.domain.*; +import org.springframework.security.acls.jdbc.BasicLookupStrategy; +import org.springframework.security.acls.jdbc.JdbcMutableAclService; +import org.springframework.security.acls.jdbc.LookupStrategy; +import org.springframework.security.acls.model.PermissionGrantingStrategy; +import org.springframework.security.core.authority.SimpleGrantedAuthority; + +import javax.sql.DataSource; +import java.util.Objects; + +@Configuration +public class AclConfig { + + @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") + @Autowired + private DataSource dataSource; + + @Bean + public EhCacheBasedAclCache aclCache() { + return new EhCacheBasedAclCache( + Objects.requireNonNull(aclEhCacheFactoryBean().getObject()), + permissionGrantingStrategy(), + aclAuthorizationStrategy() + ); + } + + @Bean + public EhCacheFactoryBean aclEhCacheFactoryBean() { + EhCacheFactoryBean ehCacheFactoryBean = new EhCacheFactoryBean(); + ehCacheFactoryBean.setCacheManager(aclCacheManager().getObject()); + ehCacheFactoryBean.setCacheName("aclCache"); + return ehCacheFactoryBean; + } + + @Bean + public EhCacheManagerFactoryBean aclCacheManager() { + return new EhCacheManagerFactoryBean(); + } + + @Bean + public PermissionGrantingStrategy permissionGrantingStrategy() { + return new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger()); + } + + @Bean + public AclAuthorizationStrategy aclAuthorizationStrategy() { + return new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_EDITOR")); + } + + @Bean + public MethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler() { + DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); + AclPermissionEvaluator permissionEvaluator = new AclPermissionEvaluator(aclService()); + expressionHandler.setPermissionEvaluator(permissionEvaluator); + expressionHandler.setPermissionCacheOptimizer(new AclPermissionCacheOptimizer(aclService())); + return expressionHandler; + } + + @Bean + public LookupStrategy lookupStrategy() { + return new BasicLookupStrategy(dataSource, aclCache(), aclAuthorizationStrategy(), new ConsoleAuditLogger()); + } + + @Bean + public JdbcMutableAclService aclService() { + return new JdbcMutableAclService(dataSource, lookupStrategy(), aclCache()); + } +} diff --git a/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/security/AclMethodSecurityConfiguration.java b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/security/AclMethodSecurityConfiguration.java new file mode 100644 index 00000000..b66620ba --- /dev/null +++ b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/security/AclMethodSecurityConfiguration.java @@ -0,0 +1,22 @@ +package ru.otus.spring.security; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration; + +@Configuration +@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) +public class AclMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration { + + @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") + @Autowired + MethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler; + + @Override + protected MethodSecurityExpressionHandler createExpressionHandler() { + return defaultMethodSecurityExpressionHandler; + } + +} diff --git a/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/security/SecurityConfiguration.java b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/security/SecurityConfiguration.java new file mode 100644 index 00000000..a2f0468b --- /dev/null +++ b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/security/SecurityConfiguration.java @@ -0,0 +1,42 @@ +package ru.otus.spring.security; + +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import org.springframework.security.web.SecurityFilterChain; + +import java.util.ArrayList; + +@EnableWebSecurity +public class SecurityConfiguration { + + @Bean + public SecurityFilterChain securityFilterChain( HttpSecurity http ) throws Exception { + http + .csrf().disable() + .authorizeHttpRequests( ( authorize ) -> authorize + .antMatchers( "/**", "/" ).permitAll() + ) + .formLogin(); + return http.build(); + } + + @Bean + public InMemoryUserDetailsManager userDetailsService() { + var users = new ArrayList(); + users.add( User + .withDefaultPasswordEncoder().username( "admin" ).password( "password" ).roles( "EDITOR" ) + .build() ); + users.add( User + .withDefaultPasswordEncoder().username( "user" ).password( "password" ).roles( "USER" ) + .build() ); + users.add( User + .withDefaultPasswordEncoder().username( "someone" ).password( "password" ).roles( "SOMEONE" ) + .build() ); + return new InMemoryUserDetailsManager( users ); + + } +} diff --git a/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/service/NoticeService.java b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/service/NoticeService.java new file mode 100644 index 00000000..f7f878fc --- /dev/null +++ b/2022-11/spring-26/ACL/src/main/java/ru/otus/spring/service/NoticeService.java @@ -0,0 +1,42 @@ +package ru.otus.spring.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.acls.domain.BasePermission; +import org.springframework.security.acls.domain.GrantedAuthoritySid; +import org.springframework.security.acls.domain.ObjectIdentityImpl; +import org.springframework.security.acls.domain.PrincipalSid; +import org.springframework.security.acls.model.MutableAcl; +import org.springframework.security.acls.model.MutableAclService; +import org.springframework.security.acls.model.ObjectIdentity; +import org.springframework.security.acls.model.Sid; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; +import ru.otus.spring.model.NoticeMessage; +import ru.otus.spring.repository.NoticeMessageRepository; + +@Service +public class NoticeService { + @Autowired + protected MutableAclService mutableAclService; + + @Autowired + private NoticeMessageRepository repository; + + public void add( NoticeMessage noticeMessage ) { + repository.save( noticeMessage ); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + final Sid owner = new PrincipalSid( authentication ); + ObjectIdentity oid = new ObjectIdentityImpl( noticeMessage.getClass(), noticeMessage.getId() ); + + final Sid admin = new GrantedAuthoritySid("ROLE_EDITOR"); + + MutableAcl acl = mutableAclService.createAcl( oid ); + acl.setOwner( owner ); + acl.insertAce( acl.getEntries().size(), BasePermission.ADMINISTRATION, admin, true ); + + mutableAclService.updateAcl( acl ); + + + } +} diff --git a/2022-11/spring-26/ACL/src/main/resources/application.yml b/2022-11/spring-26/ACL/src/main/resources/application.yml new file mode 100644 index 00000000..02f0a284 --- /dev/null +++ b/2022-11/spring-26/ACL/src/main/resources/application.yml @@ -0,0 +1,13 @@ +spring: + h2: + console: + enabled: true + jpa: + hibernate: + ddl-auto: none + datasource: + url: jdbc:h2:mem:testdb + +springdoc: + packages-to-scan: ru.otus.spring.rest + paths-to-match: /** \ No newline at end of file diff --git a/2022-11/spring-26/ACL/src/main/resources/data.sql b/2022-11/spring-26/ACL/src/main/resources/data.sql new file mode 100644 index 00000000..9ae11203 --- /dev/null +++ b/2022-11/spring-26/ACL/src/main/resources/data.sql @@ -0,0 +1,28 @@ +INSERT INTO system_message(id,content) VALUES +(1,'First Level Message'), +(2,'Second Level Message'), +(3,'Third Level Message'); + + +INSERT INTO acl_sid (id, principal, sid) VALUES +(1, 1, 'admin'), +(2, 1, 'user'), +(3, 0, 'ROLE_EDITOR'); + +INSERT INTO acl_class (id, class) VALUES +(1, 'ru.otus.spring.model.NoticeMessage'); + +INSERT INTO acl_object_identity (id, object_id_class, object_id_identity, parent_object, owner_sid, entries_inheriting) VALUES +(1, 1, 1, NULL, 3, 0), +(2, 1, 2, NULL, 3, 0), +(3, 1, 3, NULL, 3, 0); + +INSERT INTO acl_entry (id, acl_object_identity, ace_order, sid, mask, + granting, audit_success, audit_failure) VALUES +(1, 1, 1, 1, 1, 1, 1, 1), +(2, 1, 2, 1, 2, 1, 1, 1), +(3, 1, 3, 3, 1, 1, 1, 1), +(4, 2, 1, 2, 1, 1, 1, 1), +(5, 2, 2, 3, 1, 1, 1, 1), +(6, 3, 1, 3, 1, 1, 1, 1), +(7, 3, 2, 3, 2, 1, 1, 1); diff --git a/2022-11/spring-26/ACL/src/main/resources/schema.sql b/2022-11/spring-26/ACL/src/main/resources/schema.sql new file mode 100644 index 00000000..9f740482 --- /dev/null +++ b/2022-11/spring-26/ACL/src/main/resources/schema.sql @@ -0,0 +1,58 @@ +create table IF NOT EXISTS system_message (id integer not null, content varchar(255), primary key (id)); + +CREATE TABLE IF NOT EXISTS acl_sid ( + id bigint(20) NOT NULL AUTO_INCREMENT, + principal tinyint(1) NOT NULL, + sid varchar(100) NOT NULL, + PRIMARY KEY (id), + UNIQUE KEY unique_uk_1 (sid,principal) +); + +CREATE TABLE IF NOT EXISTS acl_class ( + id bigint(20) NOT NULL AUTO_INCREMENT, + class varchar(255) NOT NULL, + PRIMARY KEY (id), + UNIQUE KEY unique_uk_2 (class) +); + +CREATE TABLE IF NOT EXISTS acl_entry ( + id bigint(20) NOT NULL AUTO_INCREMENT, + acl_object_identity bigint(20) NOT NULL, + ace_order int(11) NOT NULL, + sid bigint(20) NOT NULL, + mask int(11) NOT NULL, + granting tinyint(1) NOT NULL, + audit_success tinyint(1) NOT NULL, + audit_failure tinyint(1) NOT NULL, + PRIMARY KEY (id), + UNIQUE KEY unique_uk_4 (acl_object_identity,ace_order) +); + +CREATE TABLE IF NOT EXISTS acl_object_identity ( + id bigint(20) NOT NULL AUTO_INCREMENT, + object_id_class bigint(20) NOT NULL, + object_id_identity bigint(20) NOT NULL, + parent_object bigint(20) DEFAULT NULL, + owner_sid bigint(20) DEFAULT NULL, + entries_inheriting tinyint(1) NOT NULL, + PRIMARY KEY (id), + UNIQUE KEY unique_uk_3 (object_id_class,object_id_identity) +); + +ALTER TABLE acl_entry +ADD FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity(id); + +ALTER TABLE acl_entry +ADD FOREIGN KEY (sid) REFERENCES acl_sid(id); + +-- +-- Constraints for table acl_object_identity +-- +ALTER TABLE acl_object_identity +ADD FOREIGN KEY (parent_object) REFERENCES acl_object_identity (id); + +ALTER TABLE acl_object_identity +ADD FOREIGN KEY (object_id_class) REFERENCES acl_class (id); + +ALTER TABLE acl_object_identity +ADD FOREIGN KEY (owner_sid) REFERENCES acl_sid (id); \ No newline at end of file diff --git a/2022-11/spring-26/ACL/src/main/resources/templates/error.html b/2022-11/spring-26/ACL/src/main/resources/templates/error.html new file mode 100644 index 00000000..f28b51df --- /dev/null +++ b/2022-11/spring-26/ACL/src/main/resources/templates/error.html @@ -0,0 +1,9 @@ + + + + + + +Вам доступ запрещён! + + diff --git a/2022-11/spring-26/ACL/src/main/resources/templates/index.html b/2022-11/spring-26/ACL/src/main/resources/templates/index.html new file mode 100644 index 00000000..79347f42 --- /dev/null +++ b/2022-11/spring-26/ACL/src/main/resources/templates/index.html @@ -0,0 +1,15 @@ + + + + + + +login +
+logout +
+h2-console +
+/swagger + + diff --git a/2022-11/spring-26/classwork/pom.xml b/2022-11/spring-26/classwork/pom.xml new file mode 100644 index 00000000..767f0081 --- /dev/null +++ b/2022-11/spring-26/classwork/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + + ru.otus + classwork + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 2.7.8 + + + + + UTF-8 + UTF-8 + 17 + + + + + org.springframework.boot + spring-boot-starter + + + + 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-maven-plugin + + + + diff --git a/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/SpringSecurityAuthorization.java b/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/SpringSecurityAuthorization.java new file mode 100644 index 00000000..6b3bf909 --- /dev/null +++ b/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/SpringSecurityAuthorization.java @@ -0,0 +1,13 @@ +package ru.otus.spring; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringSecurityAuthorization { + + public static void main(String[] args) { + SpringApplication.run(SpringSecurityAuthorization.class); + } + +} diff --git a/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/controller/PagesController.java b/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/controller/PagesController.java new file mode 100644 index 00000000..c7e8419c --- /dev/null +++ b/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/controller/PagesController.java @@ -0,0 +1,59 @@ +package ru.otus.spring.controller; + +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import ru.otus.spring.service.MyService; + +@Controller +public class PagesController { + + private final MyService myService; + + public PagesController(MyService myService) { + this.myService = myService; + } + + @GetMapping("/") + public String indexPage() { + return "index"; + } + + @GetMapping("/public") + public String publicPage() { + return "public"; + } + + @GetMapping("/user") + public String userPage() { + myService.onlyUser(); + return "user"; + } + + @GetMapping("/manager") + public String managerPage() { + return "manager"; + } + + @GetMapping("/admin") + //@Secured( "ADMIN" ) + public String adminPage() { + myService.onlyUser(); + //myService.onlyAdmin(); + return "admin"; + } + + @GetMapping("/authenticated") + public String authenticatedPage() { + UserDetails userDetails = (UserDetails) SecurityContextHolder + .getContext().getAuthentication().getPrincipal(); + System.out.println(userDetails.getUsername()); + return "authenticated"; + } + + @GetMapping("/success") + public String successPage() { + return "success"; + } +} diff --git a/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/controller/SecurityControllerAdvice.java b/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/controller/SecurityControllerAdvice.java new file mode 100644 index 00000000..bdbb5ea3 --- /dev/null +++ b/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/controller/SecurityControllerAdvice.java @@ -0,0 +1,16 @@ +package ru.otus.spring.controller; + +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +import java.util.Optional; + +@ControllerAdvice +public class SecurityControllerAdvice { + @ExceptionHandler(AccessDeniedException.class) + public ResponseEntity accessError() { + return ResponseEntity.of(Optional.of("Неудачник")); + } +} diff --git a/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/security/MethodSecurityConfiguration.java b/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/security/MethodSecurityConfiguration.java new file mode 100644 index 00000000..cacbe63f --- /dev/null +++ b/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/security/MethodSecurityConfiguration.java @@ -0,0 +1,10 @@ +package ru.otus.spring.security; + +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; + +@EnableGlobalMethodSecurity( + securedEnabled = true, + prePostEnabled = true +) +public class MethodSecurityConfiguration { +} diff --git a/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/security/SecurityConfiguration.java b/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/security/SecurityConfiguration.java new file mode 100644 index 00000000..680c68ab --- /dev/null +++ b/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/security/SecurityConfiguration.java @@ -0,0 +1,45 @@ +package ru.otus.spring.security; + +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import org.springframework.security.web.SecurityFilterChain; + +import java.util.ArrayList; + +@EnableWebSecurity +public class SecurityConfiguration { + + @Bean + public SecurityFilterChain securityFilterChain( HttpSecurity http ) throws Exception { + http + .csrf().disable() + .authorizeHttpRequests( ( authorize ) -> authorize + .antMatchers( "/public", "/" ).permitAll() + .antMatchers( "/authenticated", "/success" ).authenticated() + .antMatchers( "/manager" ).hasAnyRole( "MANAGER" ) + .antMatchers( "/user" ).hasAnyRole( "ADMIN", "USER" ) + .anyRequest().denyAll() + ) + .formLogin() + + ; + return http.build(); + } + + @Bean + public InMemoryUserDetailsManager userDetailsService() { + var users = new ArrayList(); + users.add( User + .withDefaultPasswordEncoder().username( "admin" ).password( "password" ).roles( "ADMIN" ) + .build() ); + users.add( User + .withDefaultPasswordEncoder().username( "user" ).password( "password" ).roles( "USER" ) + .build() ); + return new InMemoryUserDetailsManager( users ); + + } +} diff --git a/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/service/MyService.java b/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/service/MyService.java new file mode 100644 index 00000000..9c108f59 --- /dev/null +++ b/2022-11/spring-26/classwork/src/main/java/ru/otus/spring/service/MyService.java @@ -0,0 +1,17 @@ +package ru.otus.spring.service; + +import org.springframework.security.access.annotation.Secured; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Service; + +@Service +public class MyService { + @PreAuthorize("hasRole('ROLE_USER') && {new java.util.Random().nextInt()%2 == 0}") + public String onlyUser() { + return "My love"; + } + + @Secured("ADMIN") + public void onlyAdmin() { + } +} diff --git a/2022-11/spring-26/classwork/src/main/resources/templates/admin.html b/2022-11/spring-26/classwork/src/main/resources/templates/admin.html new file mode 100644 index 00000000..aa1c9563 --- /dev/null +++ b/2022-11/spring-26/classwork/src/main/resources/templates/admin.html @@ -0,0 +1,9 @@ + + + + + + +Страница с доступом только админу + + diff --git a/2022-11/spring-26/classwork/src/main/resources/templates/authenticated.html b/2022-11/spring-26/classwork/src/main/resources/templates/authenticated.html new file mode 100644 index 00000000..e4756c01 --- /dev/null +++ b/2022-11/spring-26/classwork/src/main/resources/templates/authenticated.html @@ -0,0 +1,9 @@ + + + + + + +Только для аторизованных + + diff --git a/2022-11/spring-26/classwork/src/main/resources/templates/error.html b/2022-11/spring-26/classwork/src/main/resources/templates/error.html new file mode 100644 index 00000000..f28b51df --- /dev/null +++ b/2022-11/spring-26/classwork/src/main/resources/templates/error.html @@ -0,0 +1,9 @@ + + + + + + +Вам доступ запрещён! + + diff --git a/2022-11/spring-26/classwork/src/main/resources/templates/index.html b/2022-11/spring-26/classwork/src/main/resources/templates/index.html new file mode 100644 index 00000000..d4c54ecd --- /dev/null +++ b/2022-11/spring-26/classwork/src/main/resources/templates/index.html @@ -0,0 +1,15 @@ + + + + + + +/public +
+/authenticated +
+/user +
+/admin + + diff --git a/2022-11/spring-26/classwork/src/main/resources/templates/manager.html b/2022-11/spring-26/classwork/src/main/resources/templates/manager.html new file mode 100644 index 00000000..dd4a77af --- /dev/null +++ b/2022-11/spring-26/classwork/src/main/resources/templates/manager.html @@ -0,0 +1,9 @@ + + + + + + +Доступ к MANAGER + + diff --git a/2022-11/spring-26/classwork/src/main/resources/templates/public.html b/2022-11/spring-26/classwork/src/main/resources/templates/public.html new file mode 100644 index 00000000..77188469 --- /dev/null +++ b/2022-11/spring-26/classwork/src/main/resources/templates/public.html @@ -0,0 +1,9 @@ + + + + + + +Доступен всем + + diff --git a/2022-11/spring-26/classwork/src/main/resources/templates/success.html b/2022-11/spring-26/classwork/src/main/resources/templates/success.html new file mode 100644 index 00000000..4e2a37cd --- /dev/null +++ b/2022-11/spring-26/classwork/src/main/resources/templates/success.html @@ -0,0 +1,9 @@ + + + + + + +Вы успешно вошли ! + + diff --git a/2022-11/spring-26/classwork/src/main/resources/templates/user.html b/2022-11/spring-26/classwork/src/main/resources/templates/user.html new file mode 100644 index 00000000..a794bc2d --- /dev/null +++ b/2022-11/spring-26/classwork/src/main/resources/templates/user.html @@ -0,0 +1,9 @@ + + + + + + +Доступ к USER + + diff --git a/2022-11/spring-26/solution2/pom.xml b/2022-11/spring-26/solution2/pom.xml new file mode 100644 index 00000000..a2c07373 --- /dev/null +++ b/2022-11/spring-26/solution2/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + + ru.otus + solution2 + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 2.7.8 + + + + + UTF-8 + UTF-8 + 17 + + + + + org.springframework.boot + spring-boot-starter + + + + 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-maven-plugin + + + + diff --git a/2022-11/spring-26/solution2/src/main/java/ru/otus/spring/SpringSecurityAuthorization.java b/2022-11/spring-26/solution2/src/main/java/ru/otus/spring/SpringSecurityAuthorization.java new file mode 100644 index 00000000..6b3bf909 --- /dev/null +++ b/2022-11/spring-26/solution2/src/main/java/ru/otus/spring/SpringSecurityAuthorization.java @@ -0,0 +1,13 @@ +package ru.otus.spring; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringSecurityAuthorization { + + public static void main(String[] args) { + SpringApplication.run(SpringSecurityAuthorization.class); + } + +} diff --git a/2022-11/spring-26/solution2/src/main/java/ru/otus/spring/controller/PagesController.java b/2022-11/spring-26/solution2/src/main/java/ru/otus/spring/controller/PagesController.java new file mode 100644 index 00000000..c2350307 --- /dev/null +++ b/2022-11/spring-26/solution2/src/main/java/ru/otus/spring/controller/PagesController.java @@ -0,0 +1,56 @@ +package ru.otus.spring.controller; + +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import ru.otus.spring.service.MyService; + +@Controller +public class PagesController { + + private final MyService myService; + + public PagesController(MyService myService) { + this.myService = myService; + } + + @GetMapping("/") + public String indexPage() { + return "index"; + } + + @GetMapping("/public") + public String publicPage() { + return "public"; + } + + @GetMapping("/user") + public String userPage() { + return "user"; + } + + @GetMapping("/manager") + public String managerPage() { + myService.onlyAdmin(); + return "manager"; + } + + @GetMapping("/admin") + public String adminPage() { + return "admin"; + } + + @GetMapping("/authenticated") + public String authenticatedPage() { + UserDetails userDetails = (UserDetails) SecurityContextHolder + .getContext().getAuthentication().getPrincipal(); + System.out.println(userDetails.getUsername()); + return "authenticated"; + } + + @GetMapping("/success") + public String successPage() { + return "success"; + } +} diff --git a/2022-11/spring-26/solution2/src/main/java/ru/otus/spring/security/MethodSecurityConfiguration.java b/2022-11/spring-26/solution2/src/main/java/ru/otus/spring/security/MethodSecurityConfiguration.java new file mode 100644 index 00000000..d7fe2d0d --- /dev/null +++ b/2022-11/spring-26/solution2/src/main/java/ru/otus/spring/security/MethodSecurityConfiguration.java @@ -0,0 +1,7 @@ +package ru.otus.spring.security; + +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; + +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class MethodSecurityConfiguration { +} diff --git a/2022-11/spring-26/solution2/src/main/java/ru/otus/spring/security/SecurityConfiguration.java b/2022-11/spring-26/solution2/src/main/java/ru/otus/spring/security/SecurityConfiguration.java new file mode 100644 index 00000000..b0dadc85 --- /dev/null +++ b/2022-11/spring-26/solution2/src/main/java/ru/otus/spring/security/SecurityConfiguration.java @@ -0,0 +1,51 @@ +package ru.otus.spring.security; + +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import org.springframework.security.web.SecurityFilterChain; + +import java.util.ArrayList; + +@EnableWebSecurity +public class SecurityConfiguration { + + + @Bean + public SecurityFilterChain securityFilterChain( HttpSecurity http ) throws Exception { + http + .csrf().disable() +// .sessionManagement().sessionCreationPolicy( SessionCreationPolicy.STATELESS) +// .and() + .authorizeHttpRequests( ( authorize ) -> authorize + .antMatchers( "/public", "/" ).permitAll() + .antMatchers( "/authenticated", "/success" ).authenticated() + .antMatchers( "/manager" ).hasAnyRole( "MANAGER" ) + .antMatchers( "/user" ).hasAnyRole( "ADMIN", "USER" ) + .anyRequest().denyAll() + ) + .formLogin() + + ; + return http.build(); + } + + @Bean + public InMemoryUserDetailsManager userDetailsService() { + var users = new ArrayList(); + users.add( User + .withDefaultPasswordEncoder().username( "admin" ).password( "password" ).roles( "ADMIN" ) + .build() ); + users.add( User + .withDefaultPasswordEncoder().username( "user" ).password( "password" ).roles( "USER" ) + .build() ); + users.add( User + .withDefaultPasswordEncoder().username( "manager" ).password( "password" ).roles( "MANAGER", "USER" ) + .build() ); + return new InMemoryUserDetailsManager( users ); + + } +} diff --git a/2022-11/spring-26/solution2/src/main/java/ru/otus/spring/service/MyService.java b/2022-11/spring-26/solution2/src/main/java/ru/otus/spring/service/MyService.java new file mode 100644 index 00000000..3b316f45 --- /dev/null +++ b/2022-11/spring-26/solution2/src/main/java/ru/otus/spring/service/MyService.java @@ -0,0 +1,12 @@ +package ru.otus.spring.service; + +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Service; + +@Service +public class MyService { + + @PreAuthorize("hasRole('ADMIN')") + public void onlyAdmin() { + } +} diff --git a/2022-11/spring-26/solution2/src/main/resources/templates/admin.html b/2022-11/spring-26/solution2/src/main/resources/templates/admin.html new file mode 100644 index 00000000..aa1c9563 --- /dev/null +++ b/2022-11/spring-26/solution2/src/main/resources/templates/admin.html @@ -0,0 +1,9 @@ + + + + + + +Страница с доступом только админу + + diff --git a/2022-11/spring-26/solution2/src/main/resources/templates/authenticated.html b/2022-11/spring-26/solution2/src/main/resources/templates/authenticated.html new file mode 100644 index 00000000..e4756c01 --- /dev/null +++ b/2022-11/spring-26/solution2/src/main/resources/templates/authenticated.html @@ -0,0 +1,9 @@ + + + + + + +Только для аторизованных + + diff --git a/2022-11/spring-26/solution2/src/main/resources/templates/error.html b/2022-11/spring-26/solution2/src/main/resources/templates/error.html new file mode 100644 index 00000000..f28b51df --- /dev/null +++ b/2022-11/spring-26/solution2/src/main/resources/templates/error.html @@ -0,0 +1,9 @@ + + + + + + +Вам доступ запрещён! + + diff --git a/2022-11/spring-26/solution2/src/main/resources/templates/index.html b/2022-11/spring-26/solution2/src/main/resources/templates/index.html new file mode 100644 index 00000000..9a8b9382 --- /dev/null +++ b/2022-11/spring-26/solution2/src/main/resources/templates/index.html @@ -0,0 +1,17 @@ + + + + + + +/public +
+/authenticated +
+/user +
+/manager +
+/admin + + diff --git a/2022-11/spring-26/solution2/src/main/resources/templates/manager.html b/2022-11/spring-26/solution2/src/main/resources/templates/manager.html new file mode 100644 index 00000000..dd4a77af --- /dev/null +++ b/2022-11/spring-26/solution2/src/main/resources/templates/manager.html @@ -0,0 +1,9 @@ + + + + + + +Доступ к MANAGER + + diff --git a/2022-11/spring-26/solution2/src/main/resources/templates/public.html b/2022-11/spring-26/solution2/src/main/resources/templates/public.html new file mode 100644 index 00000000..77188469 --- /dev/null +++ b/2022-11/spring-26/solution2/src/main/resources/templates/public.html @@ -0,0 +1,9 @@ + + + + + + +Доступен всем + + diff --git a/2022-11/spring-26/solution2/src/main/resources/templates/success.html b/2022-11/spring-26/solution2/src/main/resources/templates/success.html new file mode 100644 index 00000000..4e2a37cd --- /dev/null +++ b/2022-11/spring-26/solution2/src/main/resources/templates/success.html @@ -0,0 +1,9 @@ + + + + + + +Вы успешно вошли ! + + diff --git a/2022-11/spring-26/solution2/src/main/resources/templates/user.html b/2022-11/spring-26/solution2/src/main/resources/templates/user.html new file mode 100644 index 00000000..a794bc2d --- /dev/null +++ b/2022-11/spring-26/solution2/src/main/resources/templates/user.html @@ -0,0 +1,9 @@ + + + + + + +Доступ к USER + +