Question

I'm trying to connect a DataSource to Spring Security using Javaconfig. I have setup an H2 in memory database with SpringBoot and using the settings below from The Spring Data tutorial. I searched through and tried the other solutions on this board such as including Component Scan with no success.

DataSource is not visible in my securityconfig with error does not resolve to a type.

Any help is greatly appreciated.

Thanks

Explicit DataSource setup /** * */ package com.baseapp.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.orm.hibernate4.HibernateExceptionTranslator;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import java.sql.SQLException;

@Configuration
@EnableJpaRepositories(basePackages = "com.baseapp.repositories")
@EnableTransactionManagement
public class JPAConfiguration {

  @Bean
  public DataSource dataSource() throws SQLException {

    EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
    return builder.setType(EmbeddedDatabaseType.H2).build();
  }

  @Bean
  public EntityManagerFactory entityManagerFactory() throws SQLException {

    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setGenerateDdl(true);

    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setPackagesToScan("com.baseapp.models");
    factory.setDataSource(dataSource());
    factory.afterPropertiesSet();

    return factory.getObject();
  }

  @Bean
  public EntityManager entityManager(EntityManagerFactory entityManagerFactory) {
    return entityManagerFactory.createEntityManager();
  }

  @Bean
  public PlatformTransactionManager transactionManager() throws SQLException {

    JpaTransactionManager txManager = new JpaTransactionManager();
    txManager.setEntityManagerFactory(entityManagerFactory());
    return txManager;
  }

  @Bean
  public HibernateExceptionTranslator hibernateExceptionTranslator() {
    return new HibernateExceptionTranslator();
  }
}



package com.baseapp.config;

//import javax.sql.DataSource;



import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;

import com.baseapp.repositories.ClientRepository;

WebSecurityConfig

@Configuration
@EnableWebMvcSecurity
@ComponentScan("com.baseapp.config.JPAConfiguration")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    DataSource dataSource;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/home","/features","/about","/contact","/signup","/forgotpassword").permitAll()
                .antMatchers("/img/**","/css/**","/js/**").permitAll()
                .anyRequest().authenticated();
        http
            .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/company")
                .permitAll()
                .and()
            .logout()
                .logoutSuccessUrl("/login")
                .permitAll();
    }

/*    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user@email.com").password("password").roles("USER");   
    }*/

   @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .jdbcAuthentication()
                .dataSource(dataSource)
                .usersByUsernameQuery(getUserQuery())
                .authoritiesByUsernameQuery(getAuthoritiesQuery());
/*                .withDefaultSchema()
                .withUser("user@user.com").password("password").roles("USER").and()
                .withUser("admin@admin.com").password("password").roles("USER", "ADMIN");*/
    }

   private String getUserQuery() {
       return "SELECT username as username, password as password FROM CLIENT WHERE username = ?"; 
   }

   private String getAuthoritiesQuery() {
       return "SELECT username as username, role as authority FROM CLIENT WHERE username = ";
   }
}

build.gradle

buildscript {
    repositories {
        maven { url "http://repo.spring.io/libs-snapshot" }
        mavenLocal()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.0.1.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
//apply plugin: 'jetty'
apply plugin: 'war'

war {
    baseName = 'baseapp'
    version = '0.1.0'
}

jar {
    baseName = 'base-app'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
    maven { url "http://repo.spring.io/libs-snapshot" }
    maven { url "https://repository.jboss.org/nexus/content/repositories/releases" }
}

//for war build
configurations {
    providedRuntime
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web") {
        // to enable jetty use uncomment line below and include starter-jetty
//      exclude module: "spring-boot-starter-tomcat"
    }
//  compile("org.springframework.boot:spring-boot-starter-jetty")
    compile("org.springframework.boot:spring-boot-starter-security")
    compile("org.thymeleaf:thymeleaf-spring4")
    testCompile("junit:junit")

    //for war build
    providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")

    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    compile("com.h2database:h2")
//  compile("org.hsqldb:hsqldb")
    compile("org.hibernate:hibernate-validator")
    compile 'org.hibernate:hibernate-entitymanager:4.0.1.Final'

}

task wrapper(type: Wrapper) {
    gradleVersion = '1.11'
}

/*jettyRunWar.contextPath = ''
jettyRun.contextPath = ''*/

Users can be loaded to H2 in data.sql file with no error. However, when try to log in through Spring Security, it fails.

insert into client(id,firstName,lastName,username,password,roles,bio) VALUES (1,'fname','lname','email@email.com','pass','USER', '');
insert into client(id,firstName,lastName,username,password,roles,bio) VALUES (2,'myname','lname','me@email.com','pass','USER', '');

Can manually authorize new user through controller. They appear in H2 database but when logout and login not recognized by Spring Security.

@RequestMapping(value="/signup", method=RequestMethod.POST)
public String newClient(@Valid Client client, BindingResult bindingResult, Model model) {


if (bindingResult.hasErrors()) {
    return "/homepages/signup";
}
else if (!clientRepository.findByUsername(client.getUsername()).isEmpty()) {
    model.addAttribute("alreadyUsed", "This email is already associated with an account.");
    return "/homepages/signup";
    }

client.setRoles("USER");
clientRepository.save(client);

Authentication authentication = new UsernamePasswordAuthenticationToken(client.getUsername(), client.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("USER"));
SecurityContextHolder.getContext().setAuthentication(authentication);

return "/clientpages/company";
Was it helpful?

Solution

The queries appear to be incorrect. First the query for a new user is incorrect. As indicated in the javadoc, it should have a result that includes 3 results in the following order: username, password, enabled (is this user enabled). You could modify your query to the following:

private String getUserQuery() {
   return "SELECT username as username, password as password, true FROM CLIENT WHERE username = ?";
}

The query for authorities is also incorrect. The query uses "role" instead of "roles" and is missing the ?. You can change the query to the following:

private String getAuthoritiesQuery() {
   return "SELECT username as username, roles as authority FROM CLIENT WHERE username = ?";
}

Note using the default login page would have displayed these errors to you. Ideally you should be see these in the console too. I created SEC-2571 to fix this. An example of using the default login page (remove loginPage from your current config) can be seen below:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .antMatchers("/", "/home","/features","/about","/contact","/signup","/forgotpassword").permitAll()
            .antMatchers("/img/**","/css/**","/js/**").permitAll()
            .anyRequest().authenticated();
    http
        .formLogin()
            .permitAll()
            .and()
        .logout()
            .logoutSuccessUrl("/login")
            .permitAll();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top