簡體   English   中英

未調用自定義 Spring UserDetailsS​​ervice

[英]Custom Spring UserDetailsService not called

我正在嘗試為當前登錄的用戶添加一些自定義數據,所以我發現我可以實現我自己的 UserDetailsS​​ervice 並將其插入 Spring,但它從未被調用,我總是將 Principal 作為用戶名字符串。

我有 UserDetailsS​​ervice 的實現:

@Service
public class UserDetailServiceImpl implements UserDetailsService {

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    ...
  }
}

我對 UserDetails 的實現:

import org.springframework.security.core.userdetails.User;

public class LoggedInUser extends User {
...
}

並嘗試以多種方式在配置(SecurityConfiguration)中設置它:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
      @Autowired
      private CustomAuthenticationProvider customAuthProvider;
      @Autowired
      private UserDetailsService userDetailServiceImpl;
      @Override
      protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(customAuthProvider);
        auth.userDetailsService(userDetailServiceImpl).passwordEncoder(passwordService.getPasswordEncoder());
      }
...
}

或者

@Autowired
  protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(customAuthProvider);
    auth.userDetailsService(userDetailServiceImpl).passwordEncoder(passwordService.getPasswordEncoder());
  }

或者

@Override
  @Bean
  public UserDetailsService userDetailsService() {
    return new UserDetailServiceImpl();
  }

沒有任何效果......我嘗試以多種方式檢索用戶信息:

  1. 在帶有 @AuthenticationPrincipal 的控制器中,我得到 null
  2. 在服務中(我收到無效的轉換錯誤):

    認證身份驗證 = SecurityContextHolder.getContext().getAuthentication(); (LoggedInUser) authentication.getPrincipal()

知道為什么它不起作用嗎? 我的 impl 類是否在其他地方被默認覆蓋? 我試圖查看日志(logging.level.org.springframework.security=TRACE)但沒有運氣:/我可以登錄,這工作正常,只是主體數據總是只有用戶名字符串而不是我的班級。

ILya Cyclone 的評論是找出問題的關鍵,再次檢查CustomAuthenticationProvider后,我注意到在返回數據時,您可以指定Principal ,它不需要只是用戶名,但您可以在那里添加自定義UserDetails ,因此自定義UserDetailsService沒有被調用,這是我假設它總是被調用的錯誤。

所以最后這足以讓自定義AuthenticationProvider與自定義UserDetails

@Service
public class CustomAuthenticationProvider implements AuthenticationProvider {

  @Autowired
  private UserService userService;

  @Autowired
  private PasswordService passwordService;

  @Override
  public Authentication authenticate(Authentication auth) throws AuthenticationException {
    String username = auth.getName();
    String password = auth.getCredentials().toString();

    User user = userService.getUserWithPermissionsByName(username);
    if (user == null) {
      throw new BadCredentialsException("invalid_username_or_pass");
    }

    if (!passwordService.passwordsMatch(password, user.getPassword())) {
      throw new BadCredentialsException("invalid_username_or_pass");
    }

    String[] permissions = user.getPermissions().stream().map((p) -> p.getName()).toArray(String[]::new);
    List<GrantedAuthority> grantedAuths = AuthorityUtils.createAuthorityList(permissions);
    return new UsernamePasswordAuthenticationToken(new LoggedInUser(user.getName(), user.getPassword(), true, true, true, true, grantedAuths, user.getId()),
        password, grantedAuths);
  }

  @Override
  public boolean supports(Class<?> auth) {
    return auth.equals(UsernamePasswordAuthenticationToken.class);
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM