Spring SecurityとSpringMVCを使用して、既存のアプリケーション(BackendAppと呼びます)と通信するWebアプリケーション(わかりやすくするためにWebAppと呼びます)を作成しています。
認証の責任をBackendAppに委任したい(2つのアプリケーションを同期する必要がないように)。
これを実装するには、WebApp(Spring Securityを実行)がRESTを介してBackendAppと通信し、ユーザーがフォームで提供したユーザー名とパスワードを使用し、BackendAppの応答に基づいて認証します200 OKまたは401 Unauthorizedです。
これを行うにはカスタム認証マネージャーを作成する必要があることを理解していますが、私は春には非常に新しく、それを実装する方法に関する情報を見つけることができません。
私はこのようなことをする必要があると信じています:
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に設定しますか?
これが記述されたら、Java構成ファイルを使用してこの認証マネージャーを使用するようにSpring Securityを構成するにはどうすればよいですか?
事前にご協力いただきありがとうございます。
以下のサンプルをご覧ください。 UsernamePasswordAuthenticationTokenを返す必要があります。プリンシパルとGrantedAuthoritiesが含まれています。私が助けることができることを願っています:)
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は、カスタムUser-DBにアクセスする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()));
}
}
最も簡単なもの:
@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);
}
最初に、カスタムAuthenticationProviderを使用するようにSpringセキュリティを構成する必要があります。したがって、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を実装する必要があります。特に、rest callが必要なauthenticate(Authentication authentication)メソッド。例えば:
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);
}
私の解決策は最初の答えとほとんど同じです:
1)認証プロバイダーを実装するクラスが必要です
@Service
@Configurable
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// Your code of custom Authentication
}
}
2)最初の回答の反対do n'tこのカスタムプロバイダーのみがある場合は、WebSecurityConfigurationに次のコードが必要です。
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return new ProviderManager(Arrays.asList((AuthenticationProvider) new AuthProvider()));
}
問題は、Springが利用可能なプロバイダーを探し、他に何も見つからない場合はデフォルトを使用することです。ただし、AuthenticationProviderの実装があるため、実装が使用されます。