Reputation: 127
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("[email protected]").password("password").roles("USER");
}*/
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery(getUserQuery())
.authoritiesByUsernameQuery(getAuthoritiesQuery());
/* .withDefaultSchema()
.withUser("[email protected]").password("password").roles("USER").and()
.withUser("[email protected]").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 protected]','pass','USER', '');
insert into client(id,firstName,lastName,username,password,roles,bio) VALUES (2,'myname','lname','[email protected]','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";
Upvotes: 0
Views: 3056
Reputation: 21740
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();
}
Upvotes: 1