jdbcAuthentication() 而不是 inMemoryAuthentication() 不授予访问权限 - Spring Security 和 Spring Data JPA [英] jdbcAuthentication() instead of inMemoryAuthentication() doesn't give access - Spring Security and Spring Data JPA
问题描述
我只是使用 spring mvc、gradle、spring security、spring data jpa 创建简单的应用程序.现在我想测试 spring security 是如何工作的,但我有一个问题.首先我给你看一些代码,然后我会提到我的问题.
I'm just creating simple app using spring mvc, gradle, spring security, spring data jpa. Now I would like to test how spring security works, but I have a problem. First I show you little code then I will mention about my problem.
结构:
Person.java
package com.test.business;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "person")
public class Person {
@Id
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
@Column(name = "password")
private String password;
@Column(name = "role")
private String role;
public Person(){
}
public Person(int id, String name, String password, String role) {
this.id = id;
this.name = name;
this.password = password;
this.role = role;
}
//setters and getters
}
PersonController.java
package com.test.controller;
import com.test.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class PersonController {
@Autowired
private PersonService personService;
@GetMapping(value="/")
@ResponseBody
public String printWelcome() {
return "home";
}
@GetMapping(value="/admin")
@ResponseBody
public String admin() {
return "admin";
}
@GetMapping(value="/user")
@ResponseBody
public String user() {
return "user";
}
}
MyWebInitializer.java
package com.test.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { RootConfig.class, SecurityConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
SecurityWebInitializer.java
package com.test.config;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityWebInitializer
extends AbstractSecurityWebApplicationInitializer {
}
RootConfig.java
package com.test.config;
import java.util.Properties;
import javax.sql.DataSource;
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.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableJpaRepositories( basePackages = {"com.test.repository"})
@PropertySource(value = { "classpath:application.properties" })
@EnableTransactionManagement
@Import({ SecurityConfig.class })
@ComponentScan(basePackages = {"com.test.service", "com.test.repository", "com.test.controller", "com.test.business"})
public class RootConfig {
@Autowired
private Environment environment;
@Autowired
private DataSource dataSource;
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
return dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setDatabase(Database.POSTGRESQL);
vendorAdapter.setGenerateDdl(true);
vendorAdapter.setShowSql(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.test.business");
factory.setDataSource(dataSource());
factory.setJpaProperties(jpaProperties());
return factory;
}
private Properties jpaProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
@Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory().getObject());
return txManager;
}
}
WebConfig.java
package com.test.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableWebMvc
@Configuration
@ComponentScan({ "com.test.controller" })
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp().prefix("/WEB-INF/views/").suffix(".jsp");
}
}
SecurityConfig.java
package com.test.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select name, password"
+ " from person where name=?")
.authoritiesByUsernameQuery("select name, role"
+ "from person where name=?");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/admin").hasRole("ADMIN")
.and()
.httpBasic(); // Authenticate users with HTTP basic authentication
}
}
在数据库中记录为 JSON:
{
"id": 1,
"name": "test1",
"password": "test1",
"role": "ADMIN"
}
问题是什么?查看 SecurityConfig.java.有 jdbcAuthentication().当我尝试访问/admin 浏览器会要求我输入用户名和密码.不幸的是,当我这样做时什么也没发生,浏览器会一遍又一遍地询问.
And what's the problem? Look at SecurityConfig.java. There is jdbcAuthentication(). When I try access to /admin browser will ask me to put username and password. Unfortunately, when I do that nothing happend and browser will ask again, and again.
我修改了一些代码.在 SecurityConfig.java 而不是 jdbcAuthentication() 我使用了 inMemoryAuthentication() 所以它看起来像:
I changed a little me code. In SecurityConfig.java instead of jdbcAuthentication() I used inMemoryAuthentication() so it looked like:
SecurityConfig.java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/admin").hasRole("ADMIN")
.and()
.httpBasic(); // Authenticate users with HTTP basic authentication
}
}
现在我尝试访问/admin.浏览器要求我输入用户名和密码,当我这样做时,我将获得对/admin 的访问权限.为什么?为什么我无法使用 jdbcAuthentication() 获得访问权限?你能给我一些建议吗?
Now I try access to /admin. Browser asks me to put username and password and when I do that I will get a access to /admin. Why is that? Why cannot I get a access using jdbcAuthentication()? May you give me some advices?
推荐答案
我猜错在你的查询中
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select name, password"
+ " from person where name=?")
.authoritiesByUsernameQuery("select name, role"
+ "from person where name=?");
jdbcAuthentication 需要
jdbcAuthentication expects
- 对于users-by-username-query:
username
、password
和enabled
- 对于authorities-by-username-query
username
和role
- for users-by-username-query :
username
,password
andenabled
- for authorities-by-username-query
username
androle
所以对你来说这应该有效:
so for you this should work:
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select name as username, password, true"
+ " from person where name=?")
.authoritiesByUsernameQuery("select name as username, role"
+ " from person where name=?");
这篇关于jdbcAuthentication() 而不是 inMemoryAuthentication() 不授予访问权限 - Spring Security 和 Spring Data JPA的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!