Quantcast
Channel: Active questions tagged redis+java - Stack Overflow
Viewing all articles
Browse latest Browse all 2204

Spring boot session redis how I can reload SecurityContext auth user from redis

$
0
0

I have a problem with my personal project , I try to use Spring boot / redis to store all session and auth user . My application works fine except it clear all SercurityContext auth user when I restart my Spring boot app and I can not call to my api anymore.

My error log :

rg.springframework.data.redis.serializer.SerializationException: Cannot deserialize    at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.deserialize(JdkSerializationRedisSerializer.java:108) ~[spring-data-redis-3.2.0.jar:3.2.0]    at org.springframework.data.redis.core.AbstractOperations.deserializeHashValue(AbstractOperations.java:380) ~[spring-data-redis-3.2.0.jar:3.2.0]    at org.springframework.data.redis.core.AbstractOperations.deserializeHashMap(AbstractOperations.java:324) ~[spring-data-redis-3.2.0.jar:3.2.0]    at org.springframework.data.redis.core.DefaultHashOperations.entries(DefaultHashOperations.java:237) ~[spring-data-redis-3.2.0.jar:3.2.0]java.lang.IllegalStateException: Could not identify any active SessionFactory having UUID 9ff9b616-141b-4520-9d8c-7491441ecc10

After several days research , I think I need implement my custom SecurityContextRepository

@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {        http                .authorizeHttpRequests(requests -> requests                        .requestMatchers("/" + apiPath +"/public/**").permitAll()                        .requestMatchers("/" + apiPath +"/**").authenticated()                        .requestMatchers("/swagger-ui/**").permitAll()                        .requestMatchers("/v3/api-docs/**").permitAll())                .csrf(AbstractHttpConfigurer::disable)                .sessionManagement(session -> session                        .maximumSessions(1)                        .maxSessionsPreventsLogin(true)                )                .securityContext(security -> security                        .securityContextRepository(MyCustomSecurityContextRepository()) // I think I need implement this                )                .httpBasic(Customizer.withDefaults());        return http.build();    }@PostMapping("/public/user/login")    public ResponseEntity<APIResponseDTO<Void>> login(HttpSession session, @RequestParam String username, @RequestParam String password) {            try {                Authentication authentication = authenticationManager.authenticate(                        new UsernamePasswordAuthenticationToken(username, password));                SecurityContextHolder.getContext().setAuthentication(authentication);                userDetails = SecurityContextHolder.getContext().getAuthentication().getPrincipal();                session.setAttribute("USER", userDetails);                session.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext());            } catch (BadCredentialsException e) {          }        }    }}

Here is my MyCustomSecurityContextRepository . But It still have a same error

public class MyCustomSecurityContextRepositoryimplements SecurityContextRepository {    private final HttpSessionSecurityContextRepository delegate;    private final RedisTemplate<String, SecurityContext> redisTemplate;    public MyCustomSecurityContextRepository(RedisTemplate<String, SecurityContext> redisTemplate) {        this.delegate = new HttpSessionSecurityContextRepository();        this.redisTemplate = redisTemplate;    }    @Override    public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {        // Attempt to load SecurityContext from Redis        SecurityContext context = redisTemplate.opsForValue().get("securityContext:" + requestResponseHolder.getRequest().getSession().getId());        // If not found in Redis, delegate to the default implementation        if (context == null) {            context = delegate.loadContext(requestResponseHolder);        }        return context;    }    @Override    public DeferredSecurityContext loadDeferredContext(HttpServletRequest request) {        return SecurityContextRepository.super.loadDeferredContext(request);    }    @Override    public void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) {        // Save SecurityContext to Redis        redisTemplate.opsForValue().set("securityContext:" + request.getSession().getId(), context);        // Delegate to the default implementation        delegate.saveContext(context, request, response);    }    @Override    public boolean containsContext(HttpServletRequest request) {        // Check if SecurityContext is present in Redis        return redisTemplate.hasKey("securityContext:" + request.getSession().getId()) || delegate.containsContext(request);    }}

My expectation is when I try to restart my spring boot , User still have authenticate and call my api normally . Really sr for my bad english


Viewing all articles
Browse latest Browse all 2204

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>