Пользовательский менеджер проверки подлинности с помощью Spring Безопасность и настройка Java
Я использую Spring Security с SpringMVC для создания веб-приложения (я буду называть это как WebApp для ясности), который говорит с существующим приложением (я буду называть это как BackendApp).
Я хочу делегировать полномочия проверки подлинности на BackendApp (так что мне не нужно синхронизировать два приложения).
Чтобы реализовать это, я хотел бы, чтобы WebApp (работающий под управлением Spring) связывался с BackendApp через REST с именем пользователя и паролем, предоставленным пользователем в форме, и аутентифицировался на основании того, отвечает ли ответ BackendApp 200 OK или 401 Несанкционированный.
Я понимаю, что мне нужно будет написать собственный Authentication Manager для этого, но я очень новичок в Spring и не могу найти никакой информации о том, как его реализовать.
Я считаю, что мне нужно будет сделать что-то вроде этого:
public class CustomAuthenticationManager implements AuthenticationManager{
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String pw = authentication.getCredentials().toString();
// Code to make rest call here and check for OK or Unauthorised.
// What do I return?
}
}
Я установил authentication.setAuthenticated(true), если он был успешным, и false, если в противном случае и это?
Как только это будет написано, как мне настроить защиту Spring для использования этого диспетчера идентификации с помощью файла конфигурации java?
Заранее благодарим за любую помощь.
Ответы
Ответ 1
Взгляните на мой пример ниже. Вы должны вернуть UsernamePasswordAuthenticationToken. Он содержит основную и уполномоченную службу. Надеюсь, что смогу помочь:)
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getPrincipal() + "";
String password = authentication.getCredentials() + "";
User user = userRepo.findOne(username);
if (user == null) {
throw new BadCredentialsException("1000");
}
if (user.isDisabled()) {
throw new DisabledException("1001");
}
if (!encoder.matches(password, user.getPassword())) {
throw new BadCredentialsException("1000");
}
List<Right> userRights = rightRepo.getUserRights(username);
return new UsernamePasswordAuthenticationToken(username, password, userRights.stream().map(x -> new SimpleGrantedAuthority(x.getName())).collect(Collectors.toList()));
}
PS: userRepo и rightRepo являются Spring -Data-JPA-репозиториями, которые обращаются к моей пользовательской базе данных
SpringSecurity JavaConfig:
@Configuration
@EnableWebMvcSecurity
public class MySecurityConfiguration extends WebSecurityConfigurerAdapter {
public MySecurityConfiguration() {
super(false);
}
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return new ProviderManager(Arrays.asList((AuthenticationProvider) new AuthProvider()));
}
}
Ответ 2
В самом простейшем:
@Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
String username = auth.getName();
String password = auth.getCredentials().toString();
// to add more logic
List<GrantedAuthority> grantedAuths = new ArrayList<>();
grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
return new UsernamePasswordAuthenticationToken(username, password, grantedAuths);
}
Ответ 3
Сначала вы должны настроить защиту Spring для использования своего пользовательского AuthenticationProvider.
Итак, в вашем spring -security.xml(или эквивалентном файле конфигурации) вы должны определить, какой класс выполняет эту функцию. Например:
<authentication-manager alias="authenticationManager">
<authentication-provider ref="myAuthenticationProvider" />
</authentication-manager>
<!-- Bean implementing AuthenticationProvider of Spring Security -->
<beans:bean id="myAuthenticationProvider" class="com.teimas.MyAutenticationProvider">
</beans:bean>
Во-вторых, вы должны реализовать AuthenticationProvider, как в вашем примере. Специально метод аутентифицирует (аутентификация аутентификации), в которой должен быть ваш вызов для отдыха. Например:
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
User user = null;
try {
//use a rest service to find the user.
//Spring security provides user login name in authentication.getPrincipal()
user = userRestService.loadUserByUsername(authentication.getPrincipal().toString());
} catch (Exception e) {
log.error("Error loading user, not found: " + e.getMessage(), e);
}
if (user == null) {
throw new UsernameNotFoundException(String.format("Invalid credentials", authentication.getPrincipal()));
} else if (!user.isEnabled()) {
throw new UsernameNotFoundException(String.format("Not found enabled user for username ", user.getUsername()));
}
//check user password stored in authentication.getCredentials() against stored password hash
if (StringUtils.isBlank(authentication.getCredentials().toString())
|| !passwordEncoder.isPasswordValid(user.getPasswordHash(), authentication.getCredentials().toString()) {
throw new BadCredentialsException("Invalid credentials");
}
//doLogin makes whatever is necesary when login is made (put info in session, load other data etc..)
return doLogin(user);
}
Ответ 4
Мое решение почти совпадает с первым ответом:
1) Вам нужен класс, который реализует поставщик проверки подлинности
@Service
@Configurable
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// Your code of custom Authentication
}
}
2). В отличие от первого ответа, не должен иметь следующий код в вашей WebSecurityConfiguration, если у вас есть только этот настраиваемый поставщик.
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return new ProviderManager(Arrays.asList((AuthenticationProvider) new AuthProvider()));
}
Проблема заключается в том, что Spring ищет доступных поставщиков и использует значение по умолчанию, если ничего не найдено. Но поскольку у вас есть реализация AuthenticationProvider - ваша реализация будет использована.