slesh
slesh

Reputation: 2007

Spring Data Rest + Spring Security without Spring boot does work?

I am trying fire up my app where I use spring data rest and spring security without Spring Boot. But I could make Spring Security works. All security beans are created but when I send a request it doesn't go through security filter chain, but directly to the controller method.

What might be wrong with my configuration? What have I missed?

@Configuration
@ComponentScan({"com.demo.gallery"})
@Import({MongoConfig.class})
public class AppConfig {

    @Bean
    public PropertySourcesPlaceholderConfigurer propertiesPropertySource() throws IOException {
        PropertySourcesPlaceholderConfigurer source = new PropertySourcesPlaceholderConfigurer();
        ResourcePropertySource propertySource = new ResourcePropertySource("classpath:application.properties");
        MutablePropertySources propertySources = new MutablePropertySources();
        propertySources.addFirst(propertySource);
        source.setPropertySources(propertySources);
        return source;
    }
}

_

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{AppConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    @Override
    protected void customizeRegistration(ServletRegistration.Dynamic registration) {
        super.customizeRegistration(registration);
        String userHome = System.getProperty("java.io.tmpdir");
        File bannersDir = Paths.get(userHome, ".gallery/banners").toFile();
        if (!bannersDir.exists()) {
            if (!bannersDir.mkdirs()) {
                throw new RuntimeException(String.format("Could create %s directory", bannersDir));
            }
        }
        registration.setMultipartConfig(new MultipartConfigElement(userHome));
    }
}

_

    @EnableMongoRepositories(basePackages = "com.demo.gallery.persistence.repository")
    public class MongoConfig extends AbstractMongoConfiguration {
    
        private final String dbName;
        private final String host;
        private final int port;
    
        public MongoConfig(@Value("${db.name}") String dbName,
                           @Value("${db.host}") String host,
                           @Value("${db.port}") int port) {
            this.dbName = dbName;
            this.host = host;
            this.port = port;
        }
    
        @Override
        protected String getDatabaseName() {
            return dbName;
        }
    
        @Override
        public MongoClient mongoClient() {
            return new MongoClient(host, port);
        }
    
        @Override
        protected Collection<String> getMappingBasePackages() {
            return Collections.singleton("com.demo.gallery.persistence.model");
        }
    }

_

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final AppUserRepository appUserRepository;

    @Autowired
    public SecurityConfig(AppUserRepository appUserRepository) {
        this.appUserRepository = appUserRepository;
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return email -> {
            AppUser appUser = appUserRepository.findByEmail(email);
            List<SimpleGrantedAuthority> authorities = appUser.getRoles().stream()
                .map(Enum::name)
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());
            return new User(appUser.getEmail(), appUser.getPassword(), authorities);
        };
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService());
    }
}

_

@Configuration
@Import({RepositoryRestMvcConfiguration.class, SecurityConfig.class})
public class WebConfig {

    @Bean
    public ResourceProcessor<Resource<Ad>> personProcessor() {
        return new ResourceProcessor<Resource<Ad>>() {
            @Override
            public Resource<Ad> process(Resource<Ad> resource) {
                String baseUri = BasicLinkBuilder.linkToCurrentMapping().toString();
                Link bannerLink = new Link(new UriTemplate(baseUri + "/api/ads/banner/{id}")
                    .with("id", TemplateVariable.VariableType.PATH_VARIABLE), "banner")
                    .expand(Collections.singletonMap("id", resource.getContent().getId()));
                resource.add(bannerLink);
                return resource;
            }
        };
    }


    @Bean
    public RepositoryRestConfigurer repositoryRestConfigurer() {
        return RepositoryRestConfigurer.withConfig(config -> {
            config.setBasePath("/api");
        });
    }
}

Here is my build.gradle file:

plugins {
    id 'war'
    id 'net.ltgt.apt' version '0.10'
    id "org.akhikhl.gretty" version "2.0.0"
}

repositories {
    mavenCentral()
    mavenLocal()
    maven {
        url 'https://repo.spring.io/libs-milestone'
    }
}

gretty {
    httpPort = 8558
    contextPath = '/'
}

group 'com.demo'
version '1.0-SNAPSHOT'

ext {
    lombockVersion = '1.16.20'
    servletapiVersion = '4.0.0'
    junitVersion = '4.12'
    springTestVersion = '5.0.5.RELEASE'
    springDataMongodbVersion = '2.1.0.M2'
    springDataRestWebMvcVersion = '3.1.0.M2'
    log4jVersion = '1.2.17'
    slf4jVersion = '1.7.25'
    logbackVersion = '1.2.3'
    springSecurityVersion = '5.0.5.RELEASE'
}

dependencies {
    compile "ch.qos.logback:logback-classic:${logbackVersion}"
    compileOnly "org.projectlombok:lombok:${lombockVersion}"
    apt "org.projectlombok:lombok:${lombockVersion}"
    testCompile "junit:junit:${junitVersion}"
    compile "org.springframework:spring-test:${springTestVersion}"
    compile "org.springframework.data:spring-data-mongodb:${springDataMongodbVersion}"
    compile "org.springframework.data:spring-data-rest-webmvc:${springDataRestWebMvcVersion}"
    compile "org.springframework.security:spring-security-web:${springSecurityVersion}"
    compile "org.springframework.security:spring-security-config:${springSecurityVersion}"
    providedCompile "javax.servlet:javax.servlet-api:${servletapiVersion}"
}

Upvotes: 2

Views: 2233

Answers (2)

slesh
slesh

Reputation: 2007

Here are a useful links additionally to @narayan-sambireddy's ones:

  1. Hello Web Security Java Configuration.

  2. Related topic on SO

Upvotes: 1

narayan-sambireddy
narayan-sambireddy

Reputation: 335

Security filter registration seems to be missing. You need to map the springSecurityFilterChain You can easily do this by extending AbstractSecurityWebApplicationInitializer and optionally overriding methods to customize the mapping.

Refer the below spring guide. Spring Security Java Config Preview: Web Security

Upvotes: 3

Related Questions