K0NRAD
9/17/2017 - 9:27 PM

Spring security configuration with raealtime access voter to lock a current user.

Spring security configuration with raealtime access voter to lock a current user.

package com.example.demo.configuration;

import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.ConfigAttribute;
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.core.Authentication;
import org.springframework.security.web.access.expression.WebExpressionVoter;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user").password("user").roles("USER");
        auth.inMemoryAuthentication()
                .withUser("admin").password("admin").roles("ADMIN");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @Formatter:off
        http.authorizeRequests()
                .antMatchers("/").access("hasRole('USER')")
                .antMatchers("/secured").access("hasRole('ADMIN')")
                .anyRequest().authenticated().accessDecisionManager(unanonimous())
            .and()
                .httpBasic();
        // @Formatter:on
    }

    @Bean
    public AccessDecisionManager unanonimous() {
        List<AccessDecisionVoter<?>> voters = Lists.newArrayList(
                new RoleVoter(),
                new AuthenticatedVoter(),
                new RealtimeLockVoter(),
                new WebExpressionVoter()
        );
        return new UnanimousBased(voters);
    }

    class RealtimeLockVoter implements AccessDecisionVoter<Object> {

        @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<ConfigAttribute> attributes) {
            if (LockedUsers.isUserLocked(authentication.getName())) {
                return ACCESS_DENIED;
            } else {
                return ACCESS_GRANTED;
            }
        }
    }

    static final class LockedUsers {
        private static final Set<String> lockedUsers = new HashSet<>();

        public static final boolean isUserLocked(String username) {
            return lockedUsers.contains(username);
        }

        public static final void setLockUser(String username) {
            lockedUsers.add(username);
        }
    }
}