Spring 安全基本身份验证未使用 CustomUserDetailsService
Spring Security Basic Auth not using CustomUserDetailsService
我的项目是最新的 Spring Boot + Jersey,我在登录验证方面遇到问题。
我的安全配置是:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
@Autowired
private DataSource datasource;
@Override
protected void configure(HttpSecurity http) throws Exception
{
http.csrf().disable().authorizeRequests()
.antMatchers("/api/user/**").permitAll()
.antMatchers("/api/**").authenticated().and().httpBasic();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(userDetailsService()).passwordEncoder(new BCryptPasswordEncoder());
auth.jdbcAuthentication().dataSource(datasource);
}
@Bean
public UserDetailsService userDetailsService()
{
return new CustomUserDetailsService(datasource);
}
}
但是当我这样做时:
@POST
@Path("authenticate")
@Produces(MediaType.APPLICATION_JSON)
public Response authenticate(@HeaderParam("username") String username, @HeaderParam("password") String password)
{
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(username, password);
Authentication authentication = this.authManager.authenticate(authenticationToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
UserDetails userDetails = this.userService.loadUserByUsername(username);
return createOkResponse(userDetails.getUsername());
}
身份验证方法在 InMemoryUserDetailsManager 内部使用,而不是我需要用于登录验证的 CustomUserDetailsService。
我该如何更改?
如果需要:
public class CustomUserDetailsService extends JdbcUserDetailsManager implements UserDetailsService
{
@Autowired
private UserRepository userRepository;
public CustomUserDetailsService(DataSource datasource)
{
setDataSource(datasource);
}
@Override
public CurrentUserInfo loadUserByUsername(String email)
throws UsernameNotFoundException
{
User user = userRepository.findByPrimaryEmailAndEnabledTrue(email);
handleUserNotFound(email, user);
return new CurrentUserInfo(user);
}
private void handleUserNotFound(String email, User user)
{
if (user == null)
{
throw new UsernameNotFoundException("No user found with email: " + email);
}
}
}
入门依赖项:
compile("org.springframework.boot:spring-boot-starter-web") {
exclude module: 'spring-boot-starter-tomcat'
}
compile "org.springframework.boot:spring-boot-starter-jetty"
compile "org.springframework.boot:spring-boot-starter-security"
compile "org.springframework.boot:spring-boot-starter-aop"
compile "org.springframework.boot:spring-boot-starter-data-jpa"
compile "org.springframework.boot:spring-boot-starter-thymeleaf"
compile "org.springframework.boot:spring-boot-starter-jersey"
compile("org.springframework.boot:spring-boot-starter-actuator") { exclude module: 'hsqldb' }
问题是您 "registering" 是一个 AuthenticationManager
仅可用于 /api
URI,它不会作为 bean 暴露给 ApplicationContext
。当使用 Spring Boot 时,将添加一个全局的,并在其中注入一个带有生成密码的默认用户。
Spring 引导自动配置将检测是否存在已经可用的 AuthenticationManager
。要注册一个全局的,只需创建一个方法,该方法将 AuthenticationManagerBuilder
作为参数并在 @Autowired
中进行注释。只要确保它没有被命名为 configure
,因为那样是行不通的。
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService()).passwordEncoder(new BCryptPasswordEncoder());
auth.jdbcAuthentication().dataSource(datasource);
}
我的项目是最新的 Spring Boot + Jersey,我在登录验证方面遇到问题。
我的安全配置是:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
@Autowired
private DataSource datasource;
@Override
protected void configure(HttpSecurity http) throws Exception
{
http.csrf().disable().authorizeRequests()
.antMatchers("/api/user/**").permitAll()
.antMatchers("/api/**").authenticated().and().httpBasic();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(userDetailsService()).passwordEncoder(new BCryptPasswordEncoder());
auth.jdbcAuthentication().dataSource(datasource);
}
@Bean
public UserDetailsService userDetailsService()
{
return new CustomUserDetailsService(datasource);
}
}
但是当我这样做时:
@POST
@Path("authenticate")
@Produces(MediaType.APPLICATION_JSON)
public Response authenticate(@HeaderParam("username") String username, @HeaderParam("password") String password)
{
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(username, password);
Authentication authentication = this.authManager.authenticate(authenticationToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
UserDetails userDetails = this.userService.loadUserByUsername(username);
return createOkResponse(userDetails.getUsername());
}
身份验证方法在 InMemoryUserDetailsManager 内部使用,而不是我需要用于登录验证的 CustomUserDetailsService。 我该如何更改?
如果需要:
public class CustomUserDetailsService extends JdbcUserDetailsManager implements UserDetailsService
{
@Autowired
private UserRepository userRepository;
public CustomUserDetailsService(DataSource datasource)
{
setDataSource(datasource);
}
@Override
public CurrentUserInfo loadUserByUsername(String email)
throws UsernameNotFoundException
{
User user = userRepository.findByPrimaryEmailAndEnabledTrue(email);
handleUserNotFound(email, user);
return new CurrentUserInfo(user);
}
private void handleUserNotFound(String email, User user)
{
if (user == null)
{
throw new UsernameNotFoundException("No user found with email: " + email);
}
}
}
入门依赖项:
compile("org.springframework.boot:spring-boot-starter-web") {
exclude module: 'spring-boot-starter-tomcat'
}
compile "org.springframework.boot:spring-boot-starter-jetty"
compile "org.springframework.boot:spring-boot-starter-security"
compile "org.springframework.boot:spring-boot-starter-aop"
compile "org.springframework.boot:spring-boot-starter-data-jpa"
compile "org.springframework.boot:spring-boot-starter-thymeleaf"
compile "org.springframework.boot:spring-boot-starter-jersey"
compile("org.springframework.boot:spring-boot-starter-actuator") { exclude module: 'hsqldb' }
问题是您 "registering" 是一个 AuthenticationManager
仅可用于 /api
URI,它不会作为 bean 暴露给 ApplicationContext
。当使用 Spring Boot 时,将添加一个全局的,并在其中注入一个带有生成密码的默认用户。
Spring 引导自动配置将检测是否存在已经可用的 AuthenticationManager
。要注册一个全局的,只需创建一个方法,该方法将 AuthenticationManagerBuilder
作为参数并在 @Autowired
中进行注释。只要确保它没有被命名为 configure
,因为那样是行不通的。
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService()).passwordEncoder(new BCryptPasswordEncoder());
auth.jdbcAuthentication().dataSource(datasource);
}