spring redis 配置子域名共享session (有点坑)


坑一  :**private String cookieName = "DTL_SESSION_ID";**

坑二 :	

 private String getCookiePath(HttpServletRequest request) {  
	        if (this.cookiePath == null) {  
	            // 此处改为返回根路径  
	            return "/";  
	        }  
	        return this.cookiePath;  
	 }  








redis添加

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
						http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
						http://www.springframework.org/schema/jee
						http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
						http://www.springframework.org/schema/context
						http://www.springframework.org/schema/context/spring-context-4.0.xsd
						http://www.springframework.org/schema/util
                        http://www.springframework.org/schema/util/spring-util-4.0.xsd"
	default-lazy-init="true">
	<description>Redis配置</description>

	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxTotal" value="${redis.maxTotal}" />
		<property name="maxIdle" value="${redis.maxIdle}" />
		<property name="minIdle" value="${redis.minIdle}" />
		<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
		<property name="testOnBorrow" value="${redis.testOnBorrow}" />
	</bean>
	
	<bean id="jedisConnectionFactory"
		class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
		<property name="hostName" value="${redis.ip}" />
		<property name="port" value="${redis.port}" />
		<property name="timeout" value="${redis.timeout}" />
		<property name="password" value="${redis.password}"></property>
		<property name="poolConfig" ref="jedisPoolConfig" />
	</bean>
	<!-- 使用jdk redis 序列化 -->
	<bean id="jdkRedisSerializer" class="cn.com.easy.redis.JdkRedisSerializer" />
	<bean id="redisTemplateWithJdkRedisSearializer" class="org.springframework.data.redis.core.RedisTemplate">
		<property name="connectionFactory" ref="jedisConnectionFactory" />
		<property name="valueSerializer" ref="jdkRedisSerializer" />
	</bean>
	<!--使用fastjson序列化 -->
	<bean id="fastjsonValueSerializer" class="cn.com.easy.redis.FastJsonRedisSerializer" />
	<bean id="redisTemplateWithFastjsonSearializer" class="org.springframework.data.redis.core.RedisTemplate">
		<property name="connectionFactory" ref="jedisConnectionFactory" />
		<property name="valueSerializer" ref="fastjsonValueSerializer" />
	</bean>
    
    <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
    </bean>
    
      <!-- 将session放入redis -->
    <bean id="redisHttpSessionConfiguration"
        class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
        <property name="httpSessionStrategy" ref="cookieHttpSessionStrategy"/>
    </bean>
    
        <!--   设置cookieName和path -->
      <bean id="defaultCookieSerializer"  
        class="org.springframework.session.web.http.DefaultCookieSerializer">  
        <property name="domainName" value=".test.com"/>
        <property name="cookieName" value="DTL_SESSION_ID" />  
        <property name="cookiePath" value="/" />  
    </bean>  
           
     <bean id="cookieHttpSessionStrategy"  
        class="org.springframework.session.web.http.CookieHttpSessionStrategy">  
        <property name="cookieSerializer" ref="defaultCookieSerializer" />  
    </bean>  
    
</beans>




web.xml 添加到最前面

<!-- Session 共享 filter -->
	<filter>
		<filter-name>springSessionRepositoryFilter</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>springSessionRepositoryFilter</filter-name>
		<url-pattern>/*</url-pattern>
		<dispatcher>REQUEST</dispatcher>
		<dispatcher>ERROR</dispatcher>
	</filter-mapping>










package cn.com.czw.front.filter;

/*
 * Copyright 2014-2016 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.
 */

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletRequest;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.session.web.http.CookieSerializer;

/**
 * The default implementation of {[@link](https://my.oschina.net/u/393) CookieSerializer}.
 *
 * [@author](https://my.oschina.net/arthor) Rob Winch
 * [@since](https://my.oschina.net/u/266547) 1.1
 */
public class CustomerCookiesSerializer implements CookieSerializer {
	private String cookieName = "DTL_SESSION_ID";

	private Boolean useSecureCookie;

	private boolean useHttpOnlyCookie = isServlet3();

	private String cookiePath;

	private int cookieMaxAge = -1;

	private String domainName;

	private Pattern domainNamePattern;

	private String jvmRoute;
	

	/*
	 * (non-Javadoc)
	 *
	 * [@see](https://my.oschina.net/weimingwei) org.springframework.session.web.http.CookieSerializer#readCookieValues(javax.
	 * servlet.http.HttpServletRequest)
	 */
	public List<String> readCookieValues(HttpServletRequest request) {
		Cookie[] cookies = request.getCookies();
		List<String> matchingCookieValues = new ArrayList<String>();
		if (cookies != null) {
			for (Cookie cookie : cookies) {
				if (this.cookieName.equals(cookie.getName())) {
					String sessionId = cookie.getValue();
					if (sessionId == null) {
						continue;
					}
					if (this.jvmRoute != null && sessionId.endsWith(this.jvmRoute)) {
						sessionId = sessionId.substring(0,
								sessionId.length() - this.jvmRoute.length());
					}
					matchingCookieValues.add(sessionId);
				}
			}
		}
		return matchingCookieValues;
	}

	/*
	 * (non-Javadoc)
	 *
	 * [@see](https://my.oschina.net/weimingwei) org.springframework.session.web.http.CookieWriter#writeCookieValue(org.
	 * springframework.session.web.http.CookieWriter.CookieValue)
	 */
	public void writeCookieValue(CookieValue cookieValue) {
		HttpServletRequest request = cookieValue.getRequest();
		HttpServletResponse response = cookieValue.getResponse();

		String requestedCookieValue = cookieValue.getCookieValue();
		String actualCookieValue = this.jvmRoute == null ? requestedCookieValue
				: requestedCookieValue + this.jvmRoute;

		Cookie sessionCookie = new Cookie(this.cookieName, actualCookieValue);
		sessionCookie.setSecure(isSecureCookie(request));
		sessionCookie.setPath(getCookiePath(request));
		String domainName = getDomainName(request);
		if (domainName != null) {
			sessionCookie.setDomain(domainName);
		}

		if (this.useHttpOnlyCookie) {
			sessionCookie.setHttpOnly(true);
		}

		if ("".equals(requestedCookieValue)) {
			sessionCookie.setMaxAge(0);
		}
		else {
			sessionCookie.setMaxAge(this.cookieMaxAge);
		}

		response.addCookie(sessionCookie);
	}

	/**
	 * Sets if a Cookie marked as secure should be used. The default is to use the value
	 * of {@link HttpServletRequest#isSecure()}.
	 *
	 * @param useSecureCookie determines if the cookie should be marked as secure.
	 */
	public void setUseSecureCookie(boolean useSecureCookie) {
		this.useSecureCookie = useSecureCookie;
	}

	/**
	 * Sets if a Cookie marked as HTTP Only should be used. The default is true in Servlet
	 * 3+ environments, else false.
	 *
	 * @param useHttpOnlyCookie determines if the cookie should be marked as HTTP Only.
	 */
	public void setUseHttpOnlyCookie(boolean useHttpOnlyCookie) {
		if (useHttpOnlyCookie && !isServlet3()) {
			throw new IllegalArgumentException(
					"You cannot set useHttpOnlyCookie to true in pre Servlet 3 environment");
		}
		this.useHttpOnlyCookie = useHttpOnlyCookie;
	}

	private boolean isSecureCookie(HttpServletRequest request) {
		if (this.useSecureCookie == null) {
			return request.isSecure();
		}
		return this.useSecureCookie;
	}

	/**
	 * Sets the path of the Cookie. The default is to use the context path from the
	 * {@link HttpServletRequest}.
	 *
	 * @param cookiePath the path of the Cookie. If null, the default of the context path
	 * will be used.
	 */
	public void setCookiePath(String cookiePath) {
		this.cookiePath = cookiePath;
	}

	public void setCookieName(String cookieName) {
		if (cookieName == null) {
			throw new IllegalArgumentException("cookieName cannot be null");
		}
		this.cookieName = cookieName;
	}

	/**
	 * Sets the maxAge property of the Cookie. The default is -1 which signals to delete
	 * the cookie when the browser is closed.
	 *
	 * @param cookieMaxAge the maxAge property of the Cookie
	 */
	public void setCookieMaxAge(int cookieMaxAge) {
		this.cookieMaxAge = cookieMaxAge;
	}

	/**
	 * Sets an explicit Domain Name. This allow the domain of "example.com" to be used
	 * when the request comes from www.example.com. This allows for sharing the cookie
	 * across subdomains. The default is to use the current domain.
	 *
	 * @param domainName the name of the domain to use. (i.e. "example.com")
	 * @throws IllegalStateException if the domainNamePattern is also set
	 */
	public void setDomainName(String domainName) {
		if (this.domainNamePattern != null) {
			throw new IllegalStateException(
					"Cannot set both domainName and domainNamePattern");
		}
		this.domainName = domainName;
	}

	/**
	 * <p>
	 * Sets a case insensitive pattern used to extract the domain name from the
	 * {@link HttpServletRequest#getServerName()}. The pattern should provide a single
	 * grouping that defines what the value is that should be matched. User's should be
	 * careful not to output malicious characters like new lines to prevent from things
	 * like <a href= "https://www.owasp.org/index.php/HTTP_Response_Splitting">HTTP
	 * Response Splitting</a>.
	 * </p>
	 *
	 * <p>
	 * If the pattern does not match, then no domain will be set. This is useful to ensure
	 * the domain is not set during development when localhost might be used.
	 * </p>
	 * <p>
	 * An example value might be "^.+?\\.(\\w+\\.[a-z]+)$". For the given input, it would
	 * provide the following explicit domain (null means no domain name is set):
	 * </p>
	 *
	 * <ul>
	 * <li>example.com - null</li>
	 * <li>child.sub.example.com - example.com</li>
	 * <li>localhost - null</li>
	 * <li>127.0.1.1 - null</li>
	 * </ul>
	 *
	 * @param domainNamePattern the case insensitive pattern to extract the domain name
	 * with
	 * @throws IllegalStateException if the domainName is also set
	 */
	public void setDomainNamePattern(String domainNamePattern) {
		if (this.domainName != null) {
			throw new IllegalStateException(
					"Cannot set both domainName and domainNamePattern");
		}
		this.domainNamePattern = Pattern.compile(domainNamePattern,
				Pattern.CASE_INSENSITIVE);
	}

	/**
	 * <p>
	 * Used to identify which JVM to route to for session affinity. With some
	 * implementations (i.e. Redis) this provides no performance benefit. However, this
	 * can help with tracing logs of a particular user. This will ensure that the value of
	 * the cookie is formatted as
	 * </p>
	 * <code>
	 * sessionId + "." jvmRoute
	 * </code>
	 * <p>
	 * To use set a custom route on each JVM instance and setup a frontend proxy to
	 * forward all requests to the JVM based on the route.
	 * </p>
	 *
	 * @param jvmRoute the JVM Route to use (i.e. "node01jvmA", "n01ja", etc)
	 */
	public void setJvmRoute(String jvmRoute) {
		this.jvmRoute = "." + jvmRoute;
	}

	private String getDomainName(HttpServletRequest request) {
		if (this.domainName != null) {
			return this.domainName;
		}
		if (this.domainNamePattern != null) {
			Matcher matcher = this.domainNamePattern.matcher(request.getServerName());
			if (matcher.matches()) {
				return matcher.group(1);
			}
		}
		return null;
	}
	
	 private String getCookiePath(HttpServletRequest request) {  
	        if (this.cookiePath == null) {  
	            // 此处改为返回根路径  
	            return "/";  
	        }  
	        return this.cookiePath;  
	 }  

	/**
	 * Returns true if the Servlet 3 APIs are detected.
	 *
	 * @return whether the Servlet 3 APIs are detected
	 */
	private boolean isServlet3() {
		try {
			ServletRequest.class.getMethod("startAsync");
			return true;
		}
		catch (NoSuchMethodException e) {
		}
		return false;
	}

}







package cn.com.czw.front.filter;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.web.http.CookieHttpSessionStrategy;

@Configuration  
@EnableRedisHttpSession   
public class HttpSessionConfig {  
     @Bean  
     public CookieHttpSessionStrategy cookieHttpSessionStrategy() {  
         CookieHttpSessionStrategy strategy = new CookieHttpSessionStrategy();  
         strategy.setCookieSerializer(new CustomerCookiesSerializer());  
         return strategy;  
     }  
}  

转载于:https://my.oschina.net/u/1052192/blog/1023394

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值