Принципал остается строкой, хотя и использует пользовательский класс сведений о пользователе в безопасности Spring - PullRequest
0 голосов
/ 06 ноября 2018

У меня есть пользовательский UserDetailsService следующим образом:

@Service
public class AuthenticatedUserService implements UserDetailsService {

    private final UserRepository userRepository;

    @Autowired
    public AuthenticatedUserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) {
        UserCredentials userCredentials = userRepository.findByUsername(username);
        if (userCredentials == null) {
            throw new UsernameNotFoundException("The user " + username + " does not exist");
        }
        return new AuthenticatedPrincipal(userCredentials);
    }
}

Мой AuthenticatedPrincipal выглядит так:

public class AuthenticatedPrincipal implements UserDetails {
    private UserCredentials userCredentials;

    public AuthenticatedPrincipal() {

    }

    public AuthenticatedPrincipal(UserCredentials userCredentials) {
        this.userCredentials = userCredentials;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> authorities = new ArrayList<>();
        ...
        return authorities;
    }

    @Override
    public String getPassword() {
        return userCredentials.getPassword();
    }

    @Override
    public String getUsername() {
        return userCredentials.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

Я использую свой сервис таким образом:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Qualifier("authenticatedUserService")
    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        // auth.ldapAuthentication()

        auth.userDetailsService(userDetailsService)
            .passwordEncoder(passwordEncoder);
    }

    ...
}

И все работает. Я могу войти просто отлично. НО я никогда не получу свой заказной директор. В каждом месте просто получить простую строку, содержащую имя пользователя. Например, я хочу реализовать пользовательский SecurityExpressionRoot.

public class CustomMethodSecurityExpressionRoot
    extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {

    public CustomMethodSecurityExpressionRoot(Authentication authentication) {
        super(authentication);
    }

    public boolean isMember(Long OrganizationId) {
        // Throws an exception, because principal is just a string
        AuthenticatedPrincipal user = (AuthenticatedPrincipal) this.getPrincipal();
        return false;
    }

То же самое происходит, когда я пытаюсь вставить его в один из моих контроллеров.

public ResponseEntity listMessages(@AuthenticationPrincipal Principal principal) {

Я не знаю, что делать и пытаться больше. Я не вижу никакой разницы в том, что я сделал и, например, в этом уроке .

Ответы [ 2 ]

0 голосов
/ 09 ноября 2018

Хорошо, мне удалось отследить и решить мою проблему. Я использую JWT и использовал пользовательский фильтр, который устанавливает аутентификацию. Вместо того, чтобы возвращать правильный Authentication объект, я использовал значение по умолчанию UsernamePasswordAuthenticationToken. Чтобы решить эту проблему, я создал собственный класс токенов:

public class TokenBasedAuthentication extends AbstractAuthenticationToken {
    private final UserDetails principal;

    public TokenBasedAuthentication(AuthenticatedPrincipal principal) {
        super(principal.getAuthorities());
        this.principal = principal;
    }

    @Override
    public boolean isAuthenticated() {
        return true;
    }

    @Override
    public UserDetails getPrincipal() {
        return principal;
    }
}

Затем в своем фильтре я создал правильный объект аутентификации:

AuthenticatedPrincipal userDetails = (AuthenticatedPrincipal) userDetailsService.loadUserByUsername(username);
TokenBasedAuthentication authentication = new TokenBasedAuthentication(userDetails);
SecurityContextHolder.getContext().setAuthentication(authentication);

Теперь я тоже получаю правильную сумму. На самом деле следовало бы это выяснить раньше, но я думаю, все хорошо.

0 голосов
/ 07 ноября 2018

попробуйте изменить основной тип с «Principal» на ваш «AuthenticatedPrincipal» в контроллере.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...