Примеры к занятию по авторизации

This commit is contained in:
kataus
2023-03-10 19:55:29 +03:00
parent 54eca05140
commit e3dd4db68e
44 changed files with 1067 additions and 0 deletions
+83
View File
@@ -0,0 +1,83 @@
<?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>spring-framework-26-acl</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.10</version>
</parent>
<properties>
<ehcache-core.version>2.6.11</ehcache-core.version>
<swagger.version>3.0.0</swagger.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>11</java.version>
</properties>
<dependencies>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Spring Security ACL и зависимости-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-acl</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>${ehcache-core.version}</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<!-- <version>1.4.198</version>-->
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -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);
}
}
@@ -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;
}
}
@@ -0,0 +1,4 @@
package ru.otus.spring.model;
public class Pack {
}
@@ -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<NoticeMessage, Integer> {
@PostFilter("hasPermission(filterObject, 'READ')")
List<NoticeMessage> findAll();
@PostAuthorize("hasPermission(returnObject, 'READ')")
NoticeMessage getById(Integer id);
@SuppressWarnings("unchecked")
@PreAuthorize("hasPermission(#noticeMessage, 'WRITE')")
NoticeMessage save(@Param("noticeMessage") NoticeMessage noticeMessage);
}
@@ -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<NoticeMessage> 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);
}
}
@@ -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());
}
}
@@ -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;
}
}
@@ -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<UserDetails>();
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 );
}
}
@@ -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 );
}
}
@@ -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: /**
@@ -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);
@@ -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);
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
</head>
<body>
Вам доступ запрещён!
</body>
</html>
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
</head>
<body>
<a th:href="@{login}">login</a>
<br>
<a th:href="@{logout}">logout</a>
<br>
<a th:href="@{h2-console}">h2-console</a>
<br>
<a th:href="@{swagger-ui.html}">/swagger</a>
</body>
</html>
+54
View File
@@ -0,0 +1,54 @@
<?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>2.7.8</version>
<relativePath/>
</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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</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 SpringSecurityAuthorization {
public static void main(String[] args) {
SpringApplication.run(SpringSecurityAuthorization.class);
}
}
@@ -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";
}
}
@@ -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<String> accessError() {
return ResponseEntity.of(Optional.of("Неудачник"));
}
}
@@ -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 {
}
@@ -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<UserDetails>();
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 );
}
}
@@ -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() {
}
}
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
</head>
<body>
Страница с доступом только админу
</body>
</html>
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
</head>
<body>
Только для аторизованных
</body>
</html>
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
</head>
<body>
Вам доступ запрещён!
</body>
</html>
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
</head>
<body>
<a th:href="@{public}">/public</a>
<br>
<a th:href="@{authenticated}">/authenticated</a>
<br>
<a th:href="@{user}">/user</a>
<br>
<a th:href="@{admin}">/admin</a>
</body>
</html>
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
</head>
<body>
Доступ к MANAGER
</body>
</html>
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
</head>
<body>
Доступен всем
</body>
</html>
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
</head>
<body>
Вы успешно вошли !
</body>
</html>
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
</head>
<body>
Доступ к USER
</body>
</html>
+54
View File
@@ -0,0 +1,54 @@
<?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>solution2</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.8</version>
<relativePath/>
</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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</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 SpringSecurityAuthorization {
public static void main(String[] args) {
SpringApplication.run(SpringSecurityAuthorization.class);
}
}
@@ -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";
}
}
@@ -0,0 +1,7 @@
package ru.otus.spring.security;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfiguration {
}
@@ -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<UserDetails>();
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 );
}
}
@@ -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() {
}
}
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
</head>
<body>
Страница с доступом только админу
</body>
</html>
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
</head>
<body>
Только для аторизованных
</body>
</html>
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
</head>
<body>
Вам доступ запрещён!
</body>
</html>
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
</head>
<body>
<a th:href="@{public}">/public</a>
<br>
<a th:href="@{authenticated}">/authenticated</a>
<br>
<a th:href="@{user}">/user</a>
<br>
<a th:href="@{manager}">/manager</a>
<br>
<a th:href="@{admin}">/admin</a>
</body>
</html>
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
</head>
<body>
Доступ к MANAGER
</body>
</html>
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
</head>
<body>
Доступен всем
</body>
</html>
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
</head>
<body>
Вы успешно вошли !
</body>
</html>
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
</head>
<body>
Доступ к USER
</body>
</html>