как сохранить данные пользователя в сеансе и перейти к контроллерам Spring REST - PullRequest
0 голосов
/ 20 июня 2020

У нас есть страница входа, где пользователь будет вводить учетные данные пользователя и внутренне вызывать еще одну службу аутентификации, где необходимо сохранить этот токен и передать его всем контроллерам REST. Я попытался настроить область bean-компонента в этом классе, но получил исключение ниже. Мы используем spring 5.x;

com.config.CustomAuthenticationProvider sessionScopedBean CustomAuthenticationProvider UserDetails !!! null 20 июня 2020 г. 11:52:37 AM org. apache .catalina.core.StandardWrapperValve invoke

java .lang.ClassCastException: org.springframework.beans.factory.support.NullBean не может быть преобразован в com.utils.UserDetails

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    private Logger logger = Logger.getLogger(getClass().getName());
    private UserDetails userDetails;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String userName = authentication.getName();
        String passWord = authentication.getCredentials().toString();

        Result response;
        try {
            response = CustomClient.authenticate(userName, passWord);
        } catch (Exception e) {
            throw new BadCredentialsException("system authentication failed");
        }
        if (response != null && response.getToken() != null) {

            //need to store this response.getToken() in session
            logger.info("Token: " + response.getToken());

            userDetails= new UserDetails();
                userDetails.setToken(response.getToken());


            logger.info("Authentication SUCCESS !!!");
            return new UsernamePasswordAuthenticationToken(userName, passWord, Collections.emptyList());
        } else {
            logger.info("Authentication FAILED...");
            throw new BadCredentialsException("authentication failed");
        }
    }

   @Bean
    @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public UserDetails sessionScopedBean() {
        logger.info(" UserDetails !!!"+userDetails);
        return userDetails;
    }

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

Ответы [ 2 ]

0 голосов
/ 20 июня 2020

Прежде всего, вы не можете создать Bean, как в вашем примере. Аннотация @Bean обрабатывается при запуске контекста приложения. UserDetails будет иметь значение null, поэтому его нельзя будет создать.

Вы создаете UserDetails после того, как контекст приложения запущен.

Вы действительно хотите сохранить сеанс в этом случае

@Configuration
public class Config {

    @Bean
    @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public UserDetails userDetails() {
        return new UserDetails();
    }

}


@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    private Logger logger = Logger.getLogger(getClass().getName());
    @Autowired
    private UserDetails userDetails;
    
}

Вы можете внедрить с помощью Autowire или конструктора

Не создавайте его вручную, просто введите его и используйте в методе, как показано ниже

userDetails.setToken(response.getToken());
0 голосов
/ 20 июня 2020

Почему вы вообще хотите создать bean-компонент с ограниченным сеансом UserDetails? Вы уже можете добиться этого, выполнив следующие действия:

@GetMapping("/abc")
public void getUserProfile(@AuthenticationPrincipal UserDetails user ) {
...
}

или

    @GetMapping("/abc")
    public void getUserProfile() {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        UserDetails user = (UserDetails) securityContext.getAuthentication().getPrincipal();
    }

Примечание:

За кулисами Spring использует HttpSessionSecurityContextRepository, чтобы сохранить SecurityContext в сеансе http и восстанавливать его при каждом запросе

И обновленный CustomAuthenticationProvider

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    private Logger logger = Logger.getLogger(getClass().getName());

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String userName = authentication.getName();
        String passWord = authentication.getCredentials().toString();

        Result response;
        try {
            response = CustomClient.authenticate(userName, passWord);
        } catch (Exception e) {
            throw new BadCredentialsException("system authentication failed");
        }
        if (response != null && response.getToken() != null) {

            //need to store this response.getToken() in session
            logger.info("Token: " + response.getToken());

            UserDetails userDetails= new UserDetails();
            userDetails.setToken(response.getToken());


            logger.info("Authentication SUCCESS !!!");
            return new UsernamePasswordAuthenticationToken(userDetails, passWord, Collections.emptyList());
        } else {
            logger.info("Authentication FAILED...");
            throw new BadCredentialsException("authentication failed");
        }
    }

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