spring-security 具有Spring安全性和Java配置的自定义身份验证管理器

ldioqlga  于 2022-11-11  发布在  Spring
关注(0)|答案(5)|浏览(168)

我正在使用Spring Security和SpringMVC创建一个Web应用程序(为了清楚起见,我将其称为WebApp),该应用程序与一个现有应用程序(我将其称为BackendApp)进行交互。
我希望将身份验证责任委托给BackendApp(这样我就不需要同步这两个应用程序)。
为了实现这一点,我希望WebApp(运行spring security)通过REST与BackendApp进行通信,用户在表单中提供用户名和密码,并根据BackendApp的响应是200 OK还是401 Unauthorized进行身份验证。
我知道我需要编写一个自定义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?
一旦写好了这个,我如何使用Java配置文件配置Spring Security来使用这个身份验证管理器呢?
提前感谢您的帮助。

yyhrrdl8

yyhrrdl81#

请看下面的示例。您必须返回一个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 (!encoder.matches(password, user.getPassword())) {
        throw new BadCredentialsException("1000");
    }
    if (user.isDisabled()) {
        throw new DisabledException("1001");
    }
    List<Right> userRights = rightRepo.getUserRights(username);
    return new UsernamePasswordAuthenticationToken(username, null, userRights.stream().map(x -> new SimpleGrantedAuthority(x.getName())).collect(Collectors.toList()));
}

PS:userRepo和rightRepo是访问我的自定义User-DB的Spring-Data-JPA存储库
SpringSecurity Java配置:

@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()));
}

}
qqrboqgw

qqrboqgw2#

在其最简单的:

@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);
    }
yjghlzjz

yjghlzjz3#

我的解答几乎与第一个答案相同:
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会寻找可用的提供者,如果没有找到其他的提供者,就使用默认的提供者。

0g0grzrc

0g0grzrc4#

首先,必须配置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,如示例中所示。特别是方法authenticate(身份验证身份验证),您的rest调用必须使用该方法。例如:

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);
}
gkl3eglg

gkl3eglg5#

这就是我使用基于组件的配置(SecurityFilterChain)和新的authorizeHttpRequests的方法

@Bean
    protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
            .authorizeHttpRequests(auth -> auth
            .antMatchers(UNPROTECTED_URLS).permitAll()
            .oauth2ResourceServer()
            .accessDeniedHandler(restAccessDeniedHandler)
            .authenticationEntryPoint(authenticationEntryPoint)
            .jwt()
            .authenticationManager(new ProviderManager(authenticationProvider)); // this is custom authenticationProvider
        return httpSecurity.build();
    }

相关问题