会话验证 - 带有微服务的 Spring Security

Posted

技术标签:

【中文标题】会话验证 - 带有微服务的 Spring Security【英文标题】:Session Validation - Spring Security with Microservices 【发布时间】:2018-09-12 03:29:36 【问题描述】:

我当前的 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");

        

    



【问题讨论】:

【参考方案1】:

在将我的 Spring Boot 父级更新为 2.0.1 Release 并将我的 Spring Cloud 版本更改为 Finchley 后,Spring Boot 解决了该问题。

注意session repositoryHttpSessionStrategy 不是必需的,

HttpSessionStrategy 现在已贬值,因为 spring session 成为 spring session 核心。

使用redisspring boot 的外部化配置,所有依赖系统都会自动使用该缓存来验证有效会话,前提是您的类路径上有弹簧安全性。

请注意,如果您使用网关模式和Zuul Proxy,请确保您的代理路由在您的应用 YML / 属性中包含 sensitive-headers: 属性,请参见以下示例:

使用 Springboot 配置共享会话缓存的示例 auth + gateway。

认证网关

spring:
  profiles: dev
  redis:
    host: localhost
    port: 6379
  session:
    store-type: redis

server:
  port:   8080

zuul:
  routes:
    # local routes
    api:
      url: forward:/api
      path: /api/**
      sensitive-headers:
    # cloud-resource
    resource:
      url: http://localhost:9002
      path: /resource/**
      strip-prefix: false
      sensitive-headers:

proxy:
  auth:
    routes:
      resource: passthru
      ui: none
      api: passthru

security:
  sessions: ALWAYS

一些安全的资源服务器

spring:
  profiles: dev
  redis:
    host: localhost
    port: 6379
  session:
    store-type: redis
  security:
    enabled: false

server:
  port:  9002

security:
  # Never create a session, but if one exists use it
  sessions: NEVER
  # don't display the auth box
  basic:
    enabled: false

management:
  security:
    enabled: false

【讨论】:

以上是关于会话验证 - 带有微服务的 Spring Security的主要内容,如果未能解决你的问题,请参考以下文章

带有会话 Cookie 的 Spring Security RememberMe 服务

带有 Spring 会话的 Spring Security SAML

带有 LDAP 注销的 Spring Security 无法删除会话

如何在新的微服务中验证现有用户

使用 React 和 Pyramid(微服务架构)进行身份验证,如何存储“会话数据”?

在 Spring Security 中使用 Oauth2 手动进行身份验证不会在整个会话期间保持 SecurityContext