我正在使用spring boot安全层来验证和授权用户。现在,我想使用多http安全配置来做一些示例应用程序。我有一个场景,就像会有两个登录页面不同的URL映射(" / managementLogin"," / othersLogin")。
我可以理解如何配置多个httpsecurity配置,但我需要验证来自两个表的用户。如果管理用户登录,我需要使用UserDetailsService
否则从管理表通过DAO层验证用户(如果有的话)用户登录我需要从other_users表中进行验证。
有人可以帮我了解如何使用UserDetailsService
配置弹出启动安全性的多http配置和dao层吗?
这是我的基本代码段,
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class ApplicationSecurity extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("userDetailsService")
UserDetailsService userDetailsService;
@Autowired
private RESTAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private RESTAuthenticationFailureHandler authenticationFailureHandler;
@Autowired
private RESTAuthenticationSuccessHandler authenticationSuccessHandler;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// for testing authentication purpose using inMemory db
/*
* auth.inMemoryAuthentication().withUser("user").password("user").roles
* ("USER").and().withUser("admin") .password("admin").roles("ADMIN");
*/
// Dao based authentication
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/", "/home").permitAll();
http.authorizeRequests().antMatchers("/rest/**").authenticated();
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
http.formLogin().successHandler(authenticationSuccessHandler);
http.formLogin().failureHandler(authenticationFailureHandler);
http.logout().logoutSuccessUrl("/");
// CSRF tokens handling
http.addFilterAfter(new CsrfTokenResponseHeaderBindingFilter(), CsrfFilter.class);
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/registerUser","/register.html");
}
@Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
}
TIA ...,
答案 0 :(得分:0)
像这样实现自定义UserDetailsService:
ranger
答案 1 :(得分:0)
使用自己的UserDetailsService实现两个DaoAuthenticationProvider,并将两个提供程序注入authenticationManager。
我不知道两个不同的登录端点的必要条件,但起初我认为这是一个坏主意。 您可以创建不同的Authentication对象,让AuthenticationManager根据支持方法选择正确的AuthenticationProvider。
答案 2 :(得分:0)
确实,您需要使用两个用户详细信息服务。但是,这还不够。我建议你用不同的顺序创建另一个ApplicationSecurity2
类。
Spring安全性建立在有序的过滤器链列表上。
请参阅answer此处提供的Dave Sayer。然后你可以根据需要处理不同的网址。
答案 3 :(得分:0)
在我的情况下,我检查了两个存储库,下面是我使用的一个示例:
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
AbstractUser user;
try {
user = clientRepository.findByUsername(username);
}
catch (Exception userException) {
try {
user = adminRepository.findByUsername(username);
}
catch (Exception adminException) {
throw new UsernameNotFoundException("No user present with username : " + username);
}
}
return user;
}
答案 4 :(得分:0)
我必须处理相同的问题,我已经在userdetail服务中自动连接了httprequest类,并获取了请求参数类型并基于此驱动我的逻辑。
答案 5 :(得分:0)
您可以按照推荐的解决方案直接解决问题,但您可以创建一个简单的技巧来定义两个不同的 UserDetailsService
,因为这里我有两个用户,一个是普通用户,另一个是编辑器:
编辑
@Log4j2
@RequiredArgsConstructor
@Service
public class EditorService implements UserDetailsService {
private final EditorRepository editorRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if(username == null || "".equals(username)){
throw new UsernameNotFoundException("null value");
}
Optional<Editor> editor = editorRepository.findByUsername(username);
if(editor.isPresent()){
log.info("created under editor service: " + editor.get());
return editor.get();
}
throw new UsernameNotFoundException("does not exists");
}
}
用户
@Log4j2
@RequiredArgsConstructor
@Service
public class UserService implements UserDetailsService {
private final UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if(username == null || "".equals(username)){
throw new UsernameNotFoundException("null");
}
Optional<User> user = userRepository.findByUsername(username);
if(user.isPresent()){
log.info("cretaed under User service : " + user.get());
return user.get();
}
throw new UsernameNotFoundException("does not exists");
}
}
然后在配置方面,我们可以使用弹簧顺序机制:
用户配置:
@EnableWebSecurity
@Configuration
@RequiredArgsConstructor
@Order(1)
public class UserWebSecurityConfig extends WebSecurityConfigurerAdapter {
private final UserService userService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers("/user/**")
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder(10);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(this.userService).passwordEncoder(passwordEncoder());
}
}
编辑器配置:
@EnableWebSecurity
@Configuration
@RequiredArgsConstructor
public class EditorWebSecurityConfig extends WebSecurityConfigurerAdapter {
private final EditorService editorService;
@Lazy
private final PasswordEncoder passwordEncoder;
@Override
protected void configure(HttpSecurity http) throws Exception {
http // all other requests handled here
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(this.editorService).passwordEncoder(passwordEncoder);
}
}