【发布时间】:2017-10-24 09:17:58
【问题描述】:
我正在尝试使用两个不同的 AuthenticationProviders 创建一个 spring 安全配置,并公开一个 rest 接口来验证凭据(这只是在开发环境中使用,将被 prod 中的 oAuth 服务替换。)但是当我注入AuthenticationManager 进入 Controller,spring 创建一个默认的 AuthenticationManager 并将其注入到 RestController 中。如何让spring注入WebSecurityConfigurationAdapter中配置的AuthenticationManager?我正在使用 spring-boot-starter-security:1.5.7.RELEASE。这是我的安全配置:
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
@Configuration
public class LocalWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
private final DevUserDetailsService devUserDetailService;
private final ServiceUserDetailService serviceUserDetailService;
@Autowired
public LocalWebSecurityConfigurationAdapter(DevUserDetailsService devUserDetailService, ServiceUserDetailService serviceUserDetailService) {
this.devUserDetailService = devUserDetailService;
this.serviceUserDetailService = serviceUserDetailService;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().authorizeRequests().antMatchers("/api/public/**").permitAll()
.antMatchers("/api/login").permitAll()
.antMatchers("/api/**").fullyAuthenticated()
.anyRequest().permitAll()
.and().exceptionHandling().authenticationEntryPoint(unauthorizedEntryPoint())
.and().httpBasic();
}
@Bean
public AuthenticationEntryPoint unauthorizedEntryPoint() {
return (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(devUserDetailService);
DaoAuthenticationProvider serviceUserAuthProvider = new DaoAuthenticationProvider();
serviceUserAuthProvider.setUserDetailsService(serviceUserDetailService);
serviceUserAuthProvider.setPasswordEncoder(passwordEncoder());
auth.authenticationProvider(serviceUserAuthProvider);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
这是我的 RestController:
@RestController
@RequestMapping("/api/login")
public class LoginController {
private final Logger log = LoggerFactory.getLogger(this.getClass());
private final AuthenticationManager authenticationManager;
public LoginController(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@RequestMapping(method = RequestMethod.POST)
public Map<String, String> login(@RequestBody Map<String, String> body) {
String user = body.get("user");
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, body.get("password"));
try {
authenticationManager.authenticate(token);
return Collections.singletonMap("status", "ok");
} catch (BadCredentialsException e) {
return Collections.singletonMap("status", "bad credentials");
} catch (AuthenticationException e) {
log.warn("Could not authenticate user {} because {}.", user, e.getMessage(), e);
return Collections.singletonMap("status", "general error");
}
}
}
由于你们可能是 spring 的专家,是否有最佳实践来根据代码运行的环境(使用配置文件)创建不同的安全配置而不创建冗余代码?我尝试了一个超级类,但 spring 不太喜欢它。
【问题讨论】:
标签: java spring spring-boot spring-security dependency-injection