我们使用Spring MVC框架(包括Spring Security)来实现网页和REST Web服务。两者都应支持用户名/密码身份验证。但是,他们应该使用单独的用户数据库实现两个独立的安全领域。
我们面临的问题是Spring安全性将两个独立的身份验证提供程序合并到一个身份验证提供程序列表中,并针对两个提供程序检查所有用户名/密码对。我们如何为这两个领域提供单独的身份验证提供程序?
我们试图通过使用单独的角色/权限来区分这些领域。但是,如果使用网页的凭据对Web服务进行身份验证,则会导致403错误(Forbidden
)而不是401错误(Unauthorized
)。由于我们必须与Spring之前的实现保持完美的向后兼容性,这是一个问题。
此外,我们还尝试将配置拆分为几个非内部类(如https://stackoverflow.com/a/32756938/413337中所提议的)。但是,这也没有任何帮助。
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Configuration
@Order(1)
public static class WebServiceConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new WebServiceUsernamePasswordAuthenticationProvider());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/service/**")
.hasRole("SERVICE")
.and()
.anonymous().disable()
.httpBasic();
}
}
@Configuration
@Order(2)
public static class WebPagesConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new WebPagesUsernamePasswordAuthenticationProvider());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/", false);
}
}
}
更新:
我们已经通过创建BasicAuthenticationFilter
和UsernamePasswordAuthenticationToken
类的副本并仅将它们用于Web服务来实现解决方案。但是,我们仍然更喜欢没有代码重复的解决方案。这种方法可以为这两个领域创建单独的身份验证管理器实例吗?