Spring Security Autowire DataSource Javaconfig

时间:2014-04-22 00:23:43

标签: spring hibernate jpa spring-security spring-data

我尝试使用Javaconfig将DataSource连接到Spring Security。我已经使用SpringBoot在内存数据库中设置了H2,并使用了Spring Data教程中的设置。我搜索并尝试了这个板上的其他解决方案,例如包括组件扫描,但没有成功。

在我的securityconfig中看不到DataSource,但错误无法解析为某种类型。

非常感谢任何帮助。

由于

显式DataSource设置     / **      *      * /     包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 = ''*/

用户可以在data.sql文件中加载到H2,没有错误。但是,当尝试通过Spring Security登录时,它会失败。

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', '');

可以通过控制器手动授权新用户。它们出现在H2数据库中,但是当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";

1 个答案:

答案 0 :(得分:1)

查询似乎不正确。首先,对新用户的查询不正确。作为indicated in the javadoc,它应该具有以下顺序包含3个结果的结果:用户名,密码,已启用(此用户已启用)。您可以将查询修改为以下内容:

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

对权限的查询也不正确。查询使用“角色”而不是“角色”,并且缺少?。您可以将查询更改为以下内容:

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

注意使用默认登录页面会向您显示这些错误。理想情况下,你也应该在控制台中看到这些。我创建了SEC-2571来解决这个问题。使用默认登录页面(从当前配置中删除loginPage)的示例如下所示:

@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();
}
相关问题