Spring Security Autowire 数据源 Javaconfig
Posted
技术标签:
【中文标题】Spring Security Autowire 数据源 Javaconfig【英文标题】:Spring Security Autowire DataSource Javaconfig 【发布时间】:2014-06-06 03:47:32 【问题描述】:我正在尝试使用 Javaconfig 将 DataSource 连接到 Spring Security。我已经使用 SpringBoot 并使用 Spring Data 教程中的以下设置在内存数据库中设置了 H2。我搜索并尝试了此板上的其他解决方案,例如包括组件扫描,但均未成功。
DataSource 在我的 securityconfig 中不可见,错误未解析为类型。
非常感谢任何帮助。
谢谢
显式数据源设置 /** * */ 包 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;
网络安全配置
@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";
【问题讨论】:
如果您在内存配置中使用,一切正常吗(即您可以成功使用安全性和 EntityManager)吗?你的堆栈跟踪是什么样的? Rob,我可以在注释掉 DataSource 的情况下将用户添加到内存中。另外,如果我使用 javax.sql.DataSource 和 Autowired。直接添加到内存的用户可以使用安全登录。用户不能直接加载到 H2 数据库。 用 javax.sql.Datasource 注释掉应用程序失败原因:java.lang.Error: 未解决的编译问题:DataSource 无法解析为一个类型 你能展示你的依赖吗?如果您使用的是 maven,请发布您的 pom.xml 依赖关系通过 gradle 构建脚本处理。发布。我还意识到 @EnableAutoConfig 提供了一个 DataSource 和 EntityManager 所以我删除了 JPAConfiguration 以允许 SpringBoot 默认值。行为不变。我可以将用户添加到 H2,但 Spring Security 不会在 DataSource 中获取它们 【参考方案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();
【讨论】:
Rob,完美运行!谢谢! Spring Boot 和 Security 新手,非常感谢您的帮助。以上是关于Spring Security Autowire 数据源 Javaconfig的主要内容,如果未能解决你的问题,请参考以下文章