Session 验证 - Spring 微服务的安全性
Session Validation - Spring Security with Microservices
我当前的 Web 应用程序架构有一个网关服务器,它可以协调一堆微服务,如果给定原则通过身份验证,授权就会在网关发生,他们可以与一些下游服务对话。
下游服务获取所需的数据以识别给定的经过身份验证的客户端。然而 spring 证券违约行为开始并抛出预期:
org.springframework.security.access.AccessDeniedException: Access is denied
鉴于我可以在任何给定的微服务中使用 session id 和 + XSRF 令牌来验证用户是否已通过身份验证并知道哪个用户已登录(我目前正在使用 Http Basic)。
我的问题 是否有更简单/声明性的方法可以用来代替必须向每个微服务添加过滤器来覆盖 spring 证券默认行为? (参见我的示例伪代码)
见附图:架构。
Spring 资源服务器的网络安全配置:
@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();
}
}
Header 资源微服务的值:
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
...
计划的方法(伪代码) 将新过滤器附加到 spring 证券过滤器链,如果给定的标志为真,则允许访问安全端点。
**
* 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");
}
}
}
将我的 spring 引导父级更新为 2.0.1 Release
并将我的 spring 云版本更改为 Finchley
后,问题已通过 spring 引导解决。
注意 session repository
和 HttpSessionStrategy
不是必需的,
HttpSessionStrategy
现在贬值,因为 spring 会话成为 spring 会话核心。
使用 redis
和 spring boot
的外部化配置,所有相关系统都会自动使用该缓存来验证有效会话,前提是您的 class 具有 spring 安全性] 小路。
请注意,如果您使用的是网关模式,并且 Zuul Proxy
确保您的代理路由在您的应用 YML / 属性中包含 sensitive-headers:
属性,请参阅以下示例:
示例auth + 网关使用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
Some Secured Resource Server
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
我当前的 Web 应用程序架构有一个网关服务器,它可以协调一堆微服务,如果给定原则通过身份验证,授权就会在网关发生,他们可以与一些下游服务对话。
下游服务获取所需的数据以识别给定的经过身份验证的客户端。然而 spring 证券违约行为开始并抛出预期:
org.springframework.security.access.AccessDeniedException: Access is denied
鉴于我可以在任何给定的微服务中使用 session id 和 + XSRF 令牌来验证用户是否已通过身份验证并知道哪个用户已登录(我目前正在使用 Http Basic)。
我的问题 是否有更简单/声明性的方法可以用来代替必须向每个微服务添加过滤器来覆盖 spring 证券默认行为? (参见我的示例伪代码)
见附图:架构。
Spring 资源服务器的网络安全配置:
@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();
}
}
Header 资源微服务的值:
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
...
计划的方法(伪代码) 将新过滤器附加到 spring 证券过滤器链,如果给定的标志为真,则允许访问安全端点。
**
* 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");
}
}
}
将我的 spring 引导父级更新为 2.0.1 Release
并将我的 spring 云版本更改为 Finchley
后,问题已通过 spring 引导解决。
注意 session repository
和 HttpSessionStrategy
不是必需的,
HttpSessionStrategy
现在贬值,因为 spring 会话成为 spring 会话核心。
使用 redis
和 spring boot
的外部化配置,所有相关系统都会自动使用该缓存来验证有效会话,前提是您的 class 具有 spring 安全性] 小路。
请注意,如果您使用的是网关模式,并且 Zuul Proxy
确保您的代理路由在您的应用 YML / 属性中包含 sensitive-headers:
属性,请参阅以下示例:
示例auth + 网关使用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
Some Secured Resource Server
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