diff --git a/spring-security-core/.gitignore b/spring-security-core/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/spring-security-core/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/spring-security-core/README.md b/spring-security-core/README.md
new file mode 100644
index 0000000000..c7e0f645c7
--- /dev/null
+++ b/spring-security-core/README.md
@@ -0,0 +1,7 @@
+## @PreFilter and @PostFilter annotations
+
+### Build the Project ###
+
+```
+mvn clean install
+```
diff --git a/spring-security-core/pom.xml b/spring-security-core/pom.xml
new file mode 100644
index 0000000000..519ee73296
--- /dev/null
+++ b/spring-security-core/pom.xml
@@ -0,0 +1,168 @@
+
+ 4.0.0
+ com.baeldung
+ spring-security-core
+ 0.1-SNAPSHOT
+
+ spring-security-core
+ war
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.4.2.RELEASE
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-devtools
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+ com.h2database
+ h2
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.security
+ spring-security-test
+
+
+
+
+
+ spring-security-core
+
+
+ src/main/resources
+ true
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.8
+ 1.8
+ true
+ source
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ **/*LiveTest.java
+ **/*ManualTest.java
+
+
+
+
+
+
+
+
+
+
+
+
+
+ live
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ integration-test
+
+ test
+
+
+
+ none
+
+
+ **/*LiveTest.java
+
+
+ cargo
+
+
+
+
+
+
+
+
+
+
+
+
+ 4.3.4.RELEASE
+ 4.2.0.RELEASE
+
+
+ 4.4.5
+ 4.5.2
+
+
+ 1.7.21
+ 1.1.7
+
+
+ 5.3.3.Final
+ 1.2
+ 3.1.0
+ 2.8.5
+
+
+ 19.0
+ 3.5
+
+
+ 1.3
+ 4.12
+ 1.10.19
+
+ 2.9.0
+
+
+ 3.6.0
+ 2.6
+ 2.19.1
+ 1.6.1
+
+
+
diff --git a/spring-security-core/src/main/java/org/baeldung/app/App.java b/spring-security-core/src/main/java/org/baeldung/app/App.java
new file mode 100644
index 0000000000..06c295fcd7
--- /dev/null
+++ b/spring-security-core/src/main/java/org/baeldung/app/App.java
@@ -0,0 +1,17 @@
+package org.baeldung.app;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+
+@SpringBootApplication
+@EnableJpaRepositories("org.baeldung.repository")
+@ComponentScan("org.baeldung")
+@EntityScan("org.baeldung.entity")
+public class App {
+ public static void main(String[] args) {
+ SpringApplication.run(App.class, args);
+ }
+}
diff --git a/spring-security-core/src/main/java/org/baeldung/config/DatabaseLoader.java b/spring-security-core/src/main/java/org/baeldung/config/DatabaseLoader.java
new file mode 100644
index 0000000000..e311f62fff
--- /dev/null
+++ b/spring-security-core/src/main/java/org/baeldung/config/DatabaseLoader.java
@@ -0,0 +1,23 @@
+package org.baeldung.config;
+
+import org.baeldung.entity.Task;
+import org.baeldung.repository.TaskRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.stereotype.Component;
+
+@Component
+public class DatabaseLoader implements CommandLineRunner {
+
+ @Autowired
+ private TaskRepository taskRepository;
+
+ @Override
+ public void run(String... strings) throws Exception {
+ this.taskRepository.save(new Task("Send a fax", "pam"));
+ this.taskRepository.save(new Task("Print a document", "pam"));
+ this.taskRepository.save(new Task("Answer the phone", "pam"));
+ this.taskRepository.save(new Task("Call a client", "jim"));
+ this.taskRepository.save(new Task("Organize a meeting", "michael"));
+ }
+}
\ No newline at end of file
diff --git a/spring-security-core/src/main/java/org/baeldung/config/WebSecurityConfig.java b/spring-security-core/src/main/java/org/baeldung/config/WebSecurityConfig.java
new file mode 100644
index 0000000000..02e60d29a2
--- /dev/null
+++ b/spring-security-core/src/main/java/org/baeldung/config/WebSecurityConfig.java
@@ -0,0 +1,39 @@
+package org.baeldung.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+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.configuration.WebSecurityConfigurerAdapter;
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http
+ .authorizeRequests()
+ .antMatchers("/css/**", "/js/**", "/loggedout").permitAll()
+ .anyRequest().authenticated()
+ .and()
+ .httpBasic()
+ .and()
+ .logout().disable()
+ .csrf().disable();
+ }
+
+ @Autowired
+ public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
+ auth
+ .inMemoryAuthentication()
+ .withUser("jim").password("jim").roles("USER")
+ .and()
+ .withUser("pam").password("pam").roles("USER")
+ .and()
+ .withUser("michael").password("michael").roles("MANAGER");
+ }
+}
diff --git a/spring-security-core/src/main/java/org/baeldung/controller/TaskController.java b/spring-security-core/src/main/java/org/baeldung/controller/TaskController.java
new file mode 100644
index 0000000000..d99109c543
--- /dev/null
+++ b/spring-security-core/src/main/java/org/baeldung/controller/TaskController.java
@@ -0,0 +1,32 @@
+package org.baeldung.controller;
+
+import org.baeldung.entity.Task;
+import org.baeldung.service.TaskService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+@Controller
+@RequestMapping("api/tasks")
+public class TaskController {
+
+ @Autowired
+ private TaskService taskService;
+
+ @RequestMapping(method = RequestMethod.GET)
+ public ResponseEntity> findAllTasks() {
+ Iterable tasks = taskService.findAll();
+
+ return ResponseEntity.ok().body(tasks);
+ }
+
+ @RequestMapping(method = RequestMethod.POST, consumes = "application/json")
+ public ResponseEntity> addTasks(@RequestBody Iterable newTasks) {
+ Iterable tasks = taskService.save(newTasks);
+
+ return ResponseEntity.ok().body(tasks);
+ }
+}
diff --git a/spring-security-core/src/main/java/org/baeldung/entity/Task.java b/spring-security-core/src/main/java/org/baeldung/entity/Task.java
new file mode 100644
index 0000000000..5d3321ef2e
--- /dev/null
+++ b/spring-security-core/src/main/java/org/baeldung/entity/Task.java
@@ -0,0 +1,46 @@
+package org.baeldung.entity;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+public class Task {
+ private @Id @GeneratedValue Long id;
+ private String description;
+
+ private String assignee;
+
+ public Task() {
+ }
+
+ public Task(String description, String assignee) {
+ this.description = description;
+ this.assignee = assignee;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getAssignee() {
+ return assignee;
+ }
+
+ public void setAssignee(String assignee) {
+ this.assignee = assignee;
+ }
+
+}
diff --git a/spring-security-core/src/main/java/org/baeldung/repository/TaskRepository.java b/spring-security-core/src/main/java/org/baeldung/repository/TaskRepository.java
new file mode 100644
index 0000000000..651b11684f
--- /dev/null
+++ b/spring-security-core/src/main/java/org/baeldung/repository/TaskRepository.java
@@ -0,0 +1,8 @@
+package org.baeldung.repository;
+
+import org.baeldung.entity.Task;
+import org.springframework.data.repository.CrudRepository;
+
+public interface TaskRepository extends CrudRepository {
+
+}
diff --git a/spring-security-core/src/main/java/org/baeldung/service/TaskService.java b/spring-security-core/src/main/java/org/baeldung/service/TaskService.java
new file mode 100644
index 0000000000..4a0dae3aac
--- /dev/null
+++ b/spring-security-core/src/main/java/org/baeldung/service/TaskService.java
@@ -0,0 +1,26 @@
+package org.baeldung.service;
+
+import org.baeldung.entity.Task;
+import org.baeldung.repository.TaskRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PostFilter;
+import org.springframework.security.access.prepost.PreFilter;
+import org.springframework.stereotype.Service;
+
+@Service
+public class TaskService {
+
+ @Autowired
+ private TaskRepository taskRepository;
+
+ @PostFilter("hasRole('MANAGER') or filterObject.assignee == authentication.name")
+ public Iterable findAll() {
+ return taskRepository.findAll();
+ }
+
+ @PreFilter("hasRole('MANAGER') or filterObject.assignee == authentication.name")
+ public Iterable save(Iterable entities) {
+ return taskRepository.save(entities);
+ }
+
+}
diff --git a/spring-security-core/src/test/java/org/baeldung/test/LiveTest.java b/spring-security-core/src/test/java/org/baeldung/test/LiveTest.java
new file mode 100644
index 0000000000..596476d058
--- /dev/null
+++ b/spring-security-core/src/test/java/org/baeldung/test/LiveTest.java
@@ -0,0 +1,75 @@
+package org.baeldung.test;
+
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import org.baeldung.app.App;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringBootTest(classes = App.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class LiveTest {
+
+ @Autowired
+ private WebApplicationContext context;
+ private MockMvc mockMvc;
+
+ @Before
+ public void setUp() {
+ mockMvc = MockMvcBuilders.webAppContextSetup(context).dispatchOptions(true).build();
+ }
+
+ @Test
+ @WithMockUser(roles = "MANAGER")
+ public void givenUserIsManager_whenGetTasks_thenAllTasks() throws Exception {
+ String allTasks = "[{'id':1,'description':'Send a fax','assignee':'pam'}," +
+ "{'id':2,'description':'Print a document','assignee':'pam'}," +
+ "{'id':3,'description':'Answer the phone','assignee':'pam'}," +
+ "{'id':4,'description':'Call a client','assignee':'jim'}," +
+ "{'id':5,'description':'Organize a meeting','assignee':'michael'}]";
+
+ mockMvc.perform(get("/api/tasks")).andExpect(status().isOk()).andExpect(content().json(allTasks));
+ }
+
+ @Test
+ @WithMockUser(username = "jim")
+ public void givenUserNotManager_whenGetTasks_thenReturnAssignedToMe() throws Exception {
+ String myTasks = "[{'id':4,'description':'Call a client','assignee':'jim'}]";
+
+ mockMvc.perform(get("/api/tasks")).andExpect(status().isOk()).andExpect(content().json(myTasks));
+ }
+
+ @Test
+ @WithMockUser(roles = "MANAGER")
+ public void givenUserIsManager_whenPostTasks_thenIncludeAllTasks() throws Exception {
+ String newTasks = "[{\"description\":\"New to Michael\",\"assignee\":\"michael\"}," +
+ "{\"description\":\"New to Pam\",\"assignee\":\"pam\"}]";
+
+ mockMvc.perform(post("/api/tasks").contentType(MediaType.APPLICATION_JSON).content(newTasks)).andExpect(status().isOk()).andExpect(content().json("[{'id': 6,'description':'New to Michael','assignee':'michael'}, {'id': 7,'description':'New to Pam','assignee':'pam'}]"));
+ }
+
+ @Test
+ @WithMockUser(username = "jim")
+ public void givenUserNotManager_whenPostTasks_thenIncludeOnlyAssignedToMe() throws Exception {
+ String newTasks = "[{\"description\":\"New to Jim\",\"assignee\":\"jim\"}," +
+ "{\"description\":\"New to Pam\",\"assignee\":\"pam\"}]";
+
+ mockMvc.perform(post("/api/tasks").contentType(MediaType.APPLICATION_JSON).content(newTasks)).andExpect(status().isOk()).andExpect(content().json("[{'id': 8,'description':'New to Jim','assignee':'jim'}]"));
+ }
+
+}
diff --git a/spring-security-core/src/test/resources/.gitignore b/spring-security-core/src/test/resources/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/spring-security-core/src/test/resources/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file