diff --git a/spring-security-custom-voter/pom.xml b/spring-security-custom-voter/pom.xml
new file mode 100644
index 0000000000..800fe356b4
--- /dev/null
+++ b/spring-security-custom-voter/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+
+ org.baeldung
+ spring-security-custom-voter
+ 0.0.1-SNAPSHOT
+ war
+
+ spring-security-custom-voter
+ Custom AccessDecisionVoter with Spring Security
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.4.1.RELEASE
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/spring-security-custom-voter/src/main/java/org/baeldung/Application.java b/spring-security-custom-voter/src/main/java/org/baeldung/Application.java
new file mode 100644
index 0000000000..a9d6f3b8b1
--- /dev/null
+++ b/spring-security-custom-voter/src/main/java/org/baeldung/Application.java
@@ -0,0 +1,12 @@
+package org.baeldung;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/spring-security-custom-voter/src/main/java/org/baeldung/security/MinuteBasedVoter.java b/spring-security-custom-voter/src/main/java/org/baeldung/security/MinuteBasedVoter.java
new file mode 100644
index 0000000000..8d22c52b0d
--- /dev/null
+++ b/spring-security-custom-voter/src/main/java/org/baeldung/security/MinuteBasedVoter.java
@@ -0,0 +1,38 @@
+package org.baeldung.security;
+
+import org.springframework.security.access.AccessDecisionVoter;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+
+import java.time.LocalDateTime;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class MinuteBasedVoter implements AccessDecisionVoter {
+ @Override
+ public boolean supports(ConfigAttribute attribute) {
+ return true;
+ }
+
+ @Override
+ public boolean supports(Class clazz) {
+ return true;
+ }
+
+ @Override
+ public int vote(Authentication authentication, Object object, Collection collection) {
+ List roles = authentication
+ .getAuthorities()
+ .stream().map(GrantedAuthority::getAuthority)
+ .collect(Collectors.toList());
+
+ for (String role: roles) {
+ if ("ROLE_USER".equals(role) && LocalDateTime.now().getMinute() % 2 != 0) {
+ return ACCESS_DENIED;
+ }
+ }
+ return ACCESS_ABSTAIN;
+ }
+}
diff --git a/spring-security-custom-voter/src/main/java/org/baeldung/security/WebSecurityConfig.java b/spring-security-custom-voter/src/main/java/org/baeldung/security/WebSecurityConfig.java
new file mode 100644
index 0000000000..b3fb196424
--- /dev/null
+++ b/spring-security-custom-voter/src/main/java/org/baeldung/security/WebSecurityConfig.java
@@ -0,0 +1,69 @@
+package org.baeldung.security;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.access.AccessDecisionManager;
+import org.springframework.security.access.AccessDecisionVoter;
+import org.springframework.security.access.vote.AuthenticatedVoter;
+import org.springframework.security.access.vote.RoleVoter;
+import org.springframework.security.access.vote.UnanimousBased;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+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;
+import org.springframework.security.web.access.expression.WebExpressionVoter;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+
+import java.util.Arrays;
+import java.util.List;
+
+@Configuration
+@EnableWebSecurity
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+ @Autowired
+ public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
+ // @formatter: off
+ auth.inMemoryAuthentication()
+ .withUser("user").password("pass").roles("USER")
+ .and()
+ .withUser("admin").password("pass").roles("ADMIN");
+ // @formatter: on
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ // @formatter: off
+ http
+ // needed so our login could work
+ .csrf()
+ .disable()
+ .authorizeRequests()
+ .anyRequest()
+ .authenticated()
+ .accessDecisionManager(accessDecisionManager())
+ .antMatchers("/").hasAnyRole("ROLE_ADMIN", "ROLE_USER")
+ .and()
+ .formLogin()
+ .permitAll()
+ .and()
+ .logout()
+ .permitAll()
+ .deleteCookies("JSESSIONID")
+ .logoutSuccessUrl("/login");
+ // @formatter: on
+ }
+
+ @Bean
+ public AccessDecisionManager accessDecisionManager() {
+ // @formatter: off
+ List> decisionVoters =
+ Arrays.asList(
+ new WebExpressionVoter(),
+ new RoleVoter(),
+ new AuthenticatedVoter(),
+ new MinuteBasedVoter());
+ // @formatter: on
+ return new UnanimousBased(decisionVoters);
+ }
+}
diff --git a/spring-security-custom-voter/src/main/java/org/baeldung/security/XmlSecurityConfig.java b/spring-security-custom-voter/src/main/java/org/baeldung/security/XmlSecurityConfig.java
new file mode 100644
index 0000000000..45e095c66e
--- /dev/null
+++ b/spring-security-custom-voter/src/main/java/org/baeldung/security/XmlSecurityConfig.java
@@ -0,0 +1,15 @@
+package org.baeldung.security;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.ImportResource;
+
+/**
+ * Created by ambrusadrianz on 09/10/2016.
+ */
+@Configuration
+//@ImportResource({"classpath:spring-security.xml"})
+public class XmlSecurityConfig {
+ public XmlSecurityConfig() {
+ super();
+ }
+}
diff --git a/spring-security-custom-voter/src/main/java/org/baeldung/web/MvcConfig.java b/spring-security-custom-voter/src/main/java/org/baeldung/web/MvcConfig.java
new file mode 100644
index 0000000000..5d38dca1ff
--- /dev/null
+++ b/spring-security-custom-voter/src/main/java/org/baeldung/web/MvcConfig.java
@@ -0,0 +1,18 @@
+package org.baeldung.web;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+
+/**
+ * Created by ambrusadrianz on 30/09/2016.
+ */
+
+@Configuration
+public class MvcConfig extends WebMvcConfigurerAdapter {
+ @Override
+ public void addViewControllers(ViewControllerRegistry registry) {
+ registry.addViewController("/").setViewName("private");
+ }
+}
diff --git a/spring-security-custom-voter/src/main/resources/spring-security.xml b/spring-security-custom-voter/src/main/resources/spring-security.xml
new file mode 100644
index 0000000000..117638289e
--- /dev/null
+++ b/spring-security-custom-voter/src/main/resources/spring-security.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-security-custom-voter/src/main/resources/templates/private.html b/spring-security-custom-voter/src/main/resources/templates/private.html
new file mode 100644
index 0000000000..5af8c7a13e
--- /dev/null
+++ b/spring-security-custom-voter/src/main/resources/templates/private.html
@@ -0,0 +1,10 @@
+
+
+
+ Private
+
+
+Congrats!
+
+
\ No newline at end of file
diff --git a/spring-security-custom-voter/src/main/webapp/WEB-INF/web.xml b/spring-security-custom-voter/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000000..d69bce35ae
--- /dev/null
+++ b/spring-security-custom-voter/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,47 @@
+
+
+
+ Spring Secured Application
+
+
+
+ mvc
+ org.springframework.web.servlet.DispatcherServlet
+ 1
+
+
+ mvc
+ /
+
+
+
+ contextClass
+
+ org.springframework.web.context.support.AnnotationConfigWebApplicationContext
+
+
+
+ contextConfigLocation
+ org.baeldung.spring.web.config
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+
+
+ springSecurityFilterChain
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+ springSecurityFilterChain
+ /*
+
+
+
\ No newline at end of file