非常感谢您提前阅读这个问题.
我在用:
spring-security-oauth2:2.0.7.RELEASEspring-cloud-security:1.0.1.RELEASEspring-session:1.0.1.RELEASE并且在单一登录(),反向代理()网关中spring-security-oauth2 OAuth2ClientContext使用spring-session(via @EnableRedisHttpSession)时,会有一个关于Redis数据存储区中持久性的问题.@EnableOAuth2Sso@EnableZuulProxy
在我看来,创建的SessionScopedJdkDynamicAopProxied 未正确保存在Redis数据存储区中.DefaultOAuth2ClientContextorg.springframework.cloud.security.oauth2.client.OAuth2ClientAutoConfiguration
@Configuration
@ConditionalOnBean(OAuth2SsoConfiguration.class)
@ConditionalOnWebApplication
protected abstract static class SessionScopedConfiguration extends BaseConfiguration {
@Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
public OAuth2ClientContext oauth2ClientContext() {
return new DefaultOAuth2ClientContext(accessTokenRequest);
}
}
Run Code Online (Sandbox Code Playgroud)
调试oauth2ClientContextwithout 的创建@EnableRedisHttpSession表明(如预期的那样)bean将在每个客户端会话中实例化一次并存储在HttpSession.然后,这个实例将被重用存储获取的OAuth2 bearerToken除了存储的OAuth2细节accessToken在春天SecurityContext的org.springframework.security.core.Authentication.
但是,一旦使用@EnableRedisHttpSession,oauth2ClientContextbean将首先在会话创建时创建,但也将在稍后创建(同时仍使用相同的客户端会话).调试Redis客户端会话内容可确认oauth2ClientContext会话创建未正确保留:
在我们检索OAuth2之前bearerToken(NO SpringContext,NO scopedTarget.oauth2ClientContext):
~$ …Run Code Online (Sandbox Code Playgroud) spring-security spring-security-oauth2 spring-session spring-cloud
过去几天我一直在寻找如何做到这一点的最高点和最低点,并最终决定承认失败并请求帮助,拜托!
我跟随Dave Syer博士关于Angular和Spring Security的教程,特别是Zuul代理作为api网关,并使用Red Session的Spring Session(https://github.com/spring-guides/tut-spring-security-and-angular-js/tree/master/double#_sso_with_oauth2_angular_js_and_spring_security_part_v)
我遇到的问题是我通过网关从具有以下标头的外部应用程序调用资源休息服务:
String plainCreds = "user:password";
byte[] plainCredsBytes = plainCreds.getBytes();
byte[] base64CredsBytes = Base64.getEncoder().encode(plainCredsBytes);
String base64Creds = new String(base64CredsBytes);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64Creds);
Run Code Online (Sandbox Code Playgroud)
要经过身份验证然后由zuul路由,然后通过redis访问资源以访问经过身份验证的会话.
问题是会话似乎只在请求响应后才在网关中提交redis.所以发生的事情是,当我使用标头调用资源服务时,我可以看到在网关和会话中发生了成功的身份验证,但是由于会话之后没有处于redis状态,因此我在资源中获得了403通过zuul路由.
但是,如果我收到错误,请获取会话ID并将其添加到标头并再次尝试,因为现在我的身份验证会话在路由后可用于资源项目.
请有人指出我如何通过网关接听我的电话进行身份验证并在同一请求中路由吗?
谢谢贾斯汀
我正在使用Spring Boot和Spring Session来控制使用ReactJS作为前端的应用程序.我的问题很简单,我尝试了几种方法来处理但没有成功.
React部分使用AJAX在登录后调用Spring REST服务(我也使用Spring Security)至少30分钟.之后,会话已经死亡,所有呼叫都会收到302,并以登录页面作为响应.这是预期的.
但我的问题是:什么是扩展后端生存时间(超过30分钟默认值)的更好方法?
// Gradle portion
compile('org.springframework.boot:spring-boot-devtools')
compile('org.springframework.boot:spring-boot-starter-jdbc')
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-starter-aop')
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.security:spring-security-test:4.1.1.RELEASE')
// Cache configuration - JDBC
compile('org.springframework.session:spring-session:1.2.2.RELEASE')
compile('org.springframework.session:spring-session-jdbc:1.2.2.RELEASE')
compile('org.springframework.boot:spring-boot-starter-jdbc')
Run Code Online (Sandbox Code Playgroud)
我习惯添加:
// A 24 hours long session
server.session.timeout = 86400
Run Code Online (Sandbox Code Playgroud)
有了这个,我能够在SPRING_SESSION表上看到我的会话存储了MAX_INACTIVE_INTERVAL = 86400.一切似乎都很好......只有30分钟.在第31分钟,我尝试点击另一个触发AJAX调用的页面,我将收到302到我的登录页面作为响应.
我使用另一种方法获得完全相同的行为,在Auth Success上设置Java:
@Component
public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
@Value("${server.session.timeout}")
private String defaultSessionTimeoutInSeconds;
@Override
public void onAuthenticationSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication authentication) throws ServletException, IOException {
request.getSession().setMaxInactiveInterval(Integer.parseInt(defaultSessionTimeoutInSeconds));
super.onAuthenticationSuccess(request, response, authentication);
}
}
Run Code Online (Sandbox Code Playgroud)
当然,我能够在数据库存储会话中验证我的号码,但30分钟后会再次删除会话.
那么,将Spring Session超时扩展到超过30分钟的正确方法是什么?由于MAX_INACTIVE_INTERVAL没有做我认为应该做的事情,那么正确的做法是什么?
我可以使用任何lib的最新版本.
PS:当我的AJAX调用(基于JQuery)接收/ login重定向以及后备情况时,我能够考虑另一种重定向整个浏览器的解决方案.
提前致谢.
更新:
我尝试了以下方法: …
我正在努力在遗留应用程序中实现 Spring Session。我按照 Spring 文档来实现会话库,一切似乎都运行良好,除了......
有一个 UI 元素通过 sitemesh 装饰在每个页面上。此 UI 元素检查会话中的对象以查看它是否应该显示。当通过 sitemesh 装饰器从会话中检索对象时,该对象为空。当我通过控制器或主要内容 JSP 访问同一个对象时,对象被填充并且一切正常。
换句话说:
Web request -> tomcat -> controller -> jsp -> jstl -> session object = ok
然后继续渲染 sitemesh decorator adds main.jsp -> jstl -> same session object is null
我想这一定是配置问题。我可以确认,当我注释掉springSessionRepositoryFilter页面时,页面呈现正确,但是我没有使用 spring 会话并点击我的 redis 服务器。如果有人有任何想法,我将不胜感激。谢谢!我的 web.xml 看起来像这样。
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0" id="WebApp_1398187215147">
<display-name>MyApplication Web Application</display-name>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name> …Run Code Online (Sandbox Code Playgroud) 由于REST服务的远程调用特性,它们处于不断变为竞争状态的状态.比赛的日常资源之一是会议.为了实用,您需要能够在流程开始时锁定资源,并在完成任务后将其提升.
现在我的问题是,Spring Session是否有任何功能来处理会话条目中的竞争条件?
或者Java中的任何其他库/框架!
我有一个spring boot(版本1.5.9.RELEASE)应用程序,它使用spring-session在Redis上存储会话.它还使用spring-security来验证用户身份.运行应用程序时,成功登录后,安全上下文包含Authentication对象.但是在运行单元测试时,我收到此错误消息Authentication should not be null.重现的代码如下:
@SpringBootApplication
public class DemoRedisDataSessionApplication {
@Configuration
@EnableWebSecurity
@EnableRedisHttpSession(redisNamespace = "demo-redis-spring-session")
public static class AppConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("0000").roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().and()
.authorizeRequests().anyRequest().fullyAuthenticated();
}
}
@RestController
public static class AppController {
@GetMapping("/secured")
public String secured() {
return "secured";
}
}
public static void main(String[] args) {
SpringApplication.run(DemoRedisDataSessionApplication.class, args);
}
}
Run Code Online (Sandbox Code Playgroud)
这是application.properties
spring.session.store-type=redis
Run Code Online (Sandbox Code Playgroud)
这是失败的测试
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class …Run Code Online (Sandbox Code Playgroud) 我正在按照本教程将 spring 会话(通过 redis)添加到我的应用程序中。http://www.baeldung.com/spring-session
我添加依赖项
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
</dependency>
Run Code Online (Sandbox Code Playgroud)
和 SessionConfig.java 类
@Configuration
@EnableRedisHttpSession
public class SessionConfig extends AbstractHttpSessionApplicationInitializer {
}
Run Code Online (Sandbox Code Playgroud)
我已经在一个空白项目中完成了此操作,并且效果很好。但我当前的项目有一些带有自定义 UserDetailsService 的自定义用户对象,这就是出现问题的地方。
Sat Apr 07 11:21:49 EDT 2018
There was an unexpected error (type=Internal Server Error, status=500).
Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.io.NotSerializableException: com.kreyzon.dollar.entity.User
Run Code Online (Sandbox Code Playgroud)
现在,我环顾四周并找到了实现此目的的建议:
@Bean
public RedisTemplate<Object, Object> sessionRedisTemplate (
RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
template.setKeySerializer(new StringRedisSerializer()); …Run Code Online (Sandbox Code Playgroud) 我们最近开始在我们的项目中使用 spring-session。这是一个遗留应用程序,我们有一些HttpSessionListener。因此,当会话过期或用户无效时,将sessionDestroyed(HttpSessionEvent se)调用会话方法。您可以HttpSession通过调用getSession()方法来获取即将被销毁的HttpSessionEvent
Spring session 也有类似的东西。Redis Session Repository 实现将触发org.springframework.session.events.SessionDestroyedEvent事件,您可以向其添加ApplicationListener以进行一些处理。
但这并不能满足我的需要。
我遇到的问题是,即使由于 2 个主要原因,它也不能用于迁移我们现有的 HttpSessionListener 以使用这些
Spring Session 触发的事件只给出即将被销毁的会话 id。它不提供整个会话对象的副本。所以如果我现有的 HttpSessionListener 有一些逻辑来使用某些属性进行某些处理,我现在不能这样做。
创建会话时没有事件。我们有 HttpSessionListener 在创建会话时会做一些工作。
那么我有什么所有选项才能获得我们在 Spring 会话中使用 HttpSessionListener 工作的功能?
我们使用的架构与spring.io 上的这个伟大指南中描述的架构非常相似。我们的网关处理身份验证,会话使用 spring-session 存储在 Redis 中。我们微服务的端点是安全的,也使用 spring-session。
在微服务中,我需要调用另一个微服务的端点。我可以通过发现客户端轻松获取 URL,但我需要提供凭据,但我不确定实现该目标的最佳方法。
我正在考虑从 HttpRequest 获取 SESSION cookie,将其存储在某种线程局部变量或请求范围 bean 中,并在 RestTemplate 中使用它来调用第二个微服务。我需要这个请求范围的 bean,因为 RestTemplate 将用于服务层,即不在 MVC 控制器中,而且我不想用我从 cookie 获得的这个会话标识符污染我的服务层方法。
有没有更好的方法来满足这种需求?Spring Cloud 中是否已经对此提供了一些支持?
非常感谢您的意见
为什么 spring.session.store-type 没有 in memory 选项。?
有什么方法可以在不编写我的 store 实现的情况下使用带有内存选项的 spring 会话吗?
我想使用 spring 会话来使用令牌休息 api
@Bean
public HttpSessionIdResolver httpSessionIdResolver() {
return HeaderHttpSessionIdResolver.xAuthToken();
}
Run Code Online (Sandbox Code Playgroud) spring-session ×10
java ×4
spring ×4
spring-cloud ×3
spring-boot ×2
locking ×1
redis ×1
session ×1
sitemesh ×1
spring-mvc ×1
spring-test ×1