我当前的 Web 应用程序架构有一个网关服务器,它协调一堆微服务,如果给定的原则经过身份验证,授权发生在网关,它们可以与一些下游服务通信。
下游服务获取所需的数据来识别给定的经过身份验证的客户端。然而,春季证券违约行为开始出现并引发预期:
org.springframework.security.access.AccessDeniedException: Access is denied
鉴于我可以在任何给定的微服务中使用会话 ID 和 + XSRF 令牌来验证用户是否经过身份验证并知道哪个用户已登录(我目前正在使用 Http Basic)。
我的问题是有一种更简单/声明性的方法可以用来代替必须向每个微服务添加过滤器来覆盖弹簧证券默认行为吗?(请参阅我的示例伪代码)
资源服务器的 Spring Web 安全配置:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public SessionRepository<ExpiringSession> sessionRepository() {
return new MapSessionRepository();
}
@Bean
HeaderHttpSessionStrategy sessionStrategy() {
return new HeaderHttpSessionStrategy();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and().authorizeRequests().anyRequest().authenticated();
final SessionRepositoryFilter<ExpiringSession> sessionRepositoryFilter = new SessionRepositoryFilter<ExpiringSession>(
sessionRepository());
sessionRepositoryFilter
.setHttpSessionStrategy(new HeaderHttpSessionStrategy());
http.addFilterBefore(sessionRepositoryFilter,
ChannelProcessingFilter.class).csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
}
public SessionRepository<ExpiringSession> getSessionRepository(){
return sessionRepository();
}
}
资源微服务的标头值:
KEY: cookie VALUE: XSRF-TOKEN=[token_value]; SESSION=[session_value]
KEY: x-requested-with VALUE: XMLHttpRequest
KEY: x-auth-token VALUE: a32302fd-589b-42e1-8b9d-1991a080e904
...
计划的方法(伪代码)将一个新过滤器附加到弹簧证券过滤器链,如果给定标志为真,则允许访问安全端点。
**
* A custom filter that can grant access to the current resource
* if there is a valid XSRF-TOKEN and SESSION present in the shared
* session cache.
*/
public class CustomAuthenticationFilter extends AnAppropriateFilterChainFilter {
@Autowired
SessionRepository sessionRepository;
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
boolean csrfTokenExists = sessionRepository.findByCsrfTokenId(request);
boolean sessionExists = sessionRepository.findBySessionId(request);
if (csrfTokenExists && sessionExists) {
// everything is okay
} else {
// invalidate the request as being authenticated
throw new InsufficientAuthenticationException("Invalid csrf + session pair");
}
}
}