/*
 * Copyright 2004-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.maculaframework.boot.security.web.config;

import org.redisson.api.RedissonClient;
import org.redisson.spring.data.connection.RedissonConnectionFactory;
import org.redisson.spring.session.config.EnableRedissonHttpSession;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.boot.web.servlet.server.Session;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.session.data.redis.config.annotation.SpringSessionRedisConnectionFactory;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.security.web.authentication.SpringSessionRememberMeServices;
import org.springframework.session.web.http.DefaultCookieSerializer;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

/**
 * <p>
 * <b>RedisHttpSessionConfig</b> 基于Spring Session的HTTP SESSION存储
 * </p>
 *
 * @author Rain
 * @since 2019-06-27
 */

@Configuration
@EnableRedisHttpSession
public class RedisHttpSessionConfig {

    private static final String REMEMBER_ME_SERVICES_CLASS = "org.springframework.security.web.authentication.RememberMeServices";

    @Value("${server.servlet.session.cookie.domain-name-pattern}")
    private String domainNamePattern;

    @Bean(name = "sessionRedisConnectionFactory")
    @ConditionalOnMissingBean(name = "sessionRedisConnectionFactory")
    @SpringSessionRedisConnectionFactory
    public RedisConnectionFactory sessionRedisConnectionFactory(@Qualifier("sessionRedissonClient") RedissonClient redissonClient) {
        return new RedissonConnectionFactory(redissonClient);
    }

    @Bean
    public DefaultCookieSerializer cookieSerializer(ServerProperties serverProperties) {
        Session.Cookie cookie = serverProperties.getServlet().getSession().getCookie();
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
        map.from(cookie::getName).to(cookieSerializer::setCookieName);
        map.from(cookie::getDomain).to(cookieSerializer::setDomainName);
        map.from(cookie::getPath).to(cookieSerializer::setCookiePath);
        map.from(cookie::getHttpOnly).to(cookieSerializer::setUseHttpOnlyCookie);
        map.from(cookie::getSecure).to(cookieSerializer::setUseSecureCookie);
        map.from(cookie::getMaxAge).to((maxAge) -> cookieSerializer.setCookieMaxAge((int) maxAge.getSeconds()));

        if (!StringUtils.isEmpty(domainNamePattern)) {
            cookieSerializer.setDomainNamePattern(domainNamePattern);
        }

        if (ClassUtils.isPresent(REMEMBER_ME_SERVICES_CLASS, getClass().getClassLoader())) {
            cookieSerializer.setRememberMeRequestAttribute(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR);
        }
        return cookieSerializer;
    }

}

@@ -771,32 +771,94 @@
 nectionFactory;%0A
+import org.redisson.spring.session.RedissonSessionRepository;%0A
 import org.redis
@@ -1301,32 +1301,94 @@
 server.Session;%0A
+import org.springframework.context.ApplicationEventPublisher;%0A
 import org.sprin
@@ -1515,52 +1515,327 @@
 ork.
-data.redis.connection.RedisConnectionFactory
+context.annotation.ImportAware;%0Aimport org.springframework.core.annotation.AnnotationAttributes;%0Aimport org.springframework.core.type.AnnotationMetadata;%0Aimport org.springframework.data.redis.connection.RedisConnectionFactory;%0Aimport org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration
 ;%0Aim
@@ -1937,105 +1937,8 @@
 ry;%0A
-import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;%0A
 impo
@@ -2188,16 +2188,39 @@
 Utils;%0A%0A
+import java.util.Map;%0A%0A
 /**%0A * %3C
@@ -2359,32 +2359,8 @@
 ion%0A
-@EnableRedisHttpSession%0A
 publ
@@ -2391,16 +2391,55 @@
 nConfig 
+extends SpringHttpSessionConfiguration 
 %7B%0A%0A    p
@@ -2674,169 +2674,234 @@
 rn;%0A
-%0A
     @
-Bean(name = %22
+Value(%22$%7Bspring.
 session
-R
+.r
 edis
-ConnectionFactory%22)%0A    @ConditionalOnMissingBean(name = %22
+.maxInactiveIntervalInSeconds:1800%7D%22)%0A    private Integer maxInactiveIntervalInSeconds;%0A    @Value(%22$%7Bspring.
 session
-R
+.r
 edis
-ConnectionFactory
+.namespace:spring:session:%7D
 %22)%0A    
-@S
 pri
-ngSessionRedisConnectionFactory
+vate String keyPrefix;%0A%0A    @Bean
 %0A   
@@ -2909,37 +2909,40 @@
 public Redis
-ConnectionFac
+sonSessionReposi
 tory session
@@ -2947,29 +2947,26 @@
 onRe
-disConnectionFactory(
+pository(%0A        
 @Qua
@@ -2996,17 +2996,16 @@
 Client%22)
- 
 Redisson
@@ -3029,72 +3029,280 @@
 ient
-) %7B%0A        return new RedissonConnectionFactory(redissonClient)
+, ApplicationEventPublisher eventPublisher) %7B%0A        RedissonSessionRepository repository = new RedissonSessionRepository(redissonClient, eventPublisher, keyPrefix);%0A        repository.setDefaultMaxInactiveInterval(maxInactiveIntervalInSeconds);%0A        return repository
 ;%0A  
@@ -4537,11 +4537,10 @@
 ;%0A    %7D%0A
-%0A
 %7D%0A

配置spring session for redis