pull/3/head
tanghc 4 years ago
parent 4456d15182
commit 57c8f34c3b
  1. 7
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java
  2. 11
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiContext.java
  3. 11
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/config/AbstractConfiguration.java
  4. 244
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/ApiHttpSession.java
  5. 30
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/ApiRedisTemplate.java
  6. 93
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/ApiSessionManager.java
  7. 269
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/RedisHttpSession.java
  8. 105
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/RedisSessionManager.java
  9. 20
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/session/SessionManager.java
  10. 2
      sop-gateway/src/main/resources/META-INF/gateway.properties

@ -27,8 +27,6 @@ import com.gitee.sop.gatewaycommon.result.ResultAppender;
import com.gitee.sop.gatewaycommon.result.ResultExecutorForGateway;
import com.gitee.sop.gatewaycommon.secret.CacheIsvManager;
import com.gitee.sop.gatewaycommon.secret.IsvManager;
import com.gitee.sop.gatewaycommon.session.ApiSessionManager;
import com.gitee.sop.gatewaycommon.session.SessionManager;
import com.gitee.sop.gatewaycommon.validate.ApiEncrypter;
import com.gitee.sop.gatewaycommon.validate.ApiSigner;
import com.gitee.sop.gatewaycommon.validate.ApiValidator;
@ -83,11 +81,6 @@ public class ApiConfig {
*/
private Validator validator = new ApiValidator();
/**
* session管理
*/
private SessionManager sessionManager = new ApiSessionManager();
/**
* isv路由权限
*/

@ -1,7 +1,5 @@
package com.gitee.sop.gatewaycommon.bean;
import com.gitee.sop.gatewaycommon.session.SessionManager;
/**
* 应用上下文,方便获取信息
*
@ -9,15 +7,6 @@ import com.gitee.sop.gatewaycommon.session.SessionManager;
*/
public class ApiContext {
/**
* 获取session管理器
*
* @return 返回SessionManager
*/
public static SessionManager getSessionManager() {
return getApiConfig().getSessionManager();
}
public static ApiConfig getApiConfig() {
return ApiConfig.getInstance();

@ -22,7 +22,6 @@ import com.gitee.sop.gatewaycommon.route.RegistryListener;
import com.gitee.sop.gatewaycommon.route.ServiceListener;
import com.gitee.sop.gatewaycommon.route.ServiceRouteListener;
import com.gitee.sop.gatewaycommon.secret.IsvManager;
import com.gitee.sop.gatewaycommon.session.SessionManager;
import com.gitee.sop.gatewaycommon.util.RouteInterceptorUtil;
import com.gitee.sop.gatewaycommon.validate.SignConfig;
import com.gitee.sop.gatewaycommon.validate.Validator;
@ -58,8 +57,8 @@ import java.util.concurrent.locks.ReentrantLock;
@Slf4j
public class AbstractConfiguration implements ApplicationContextAware, ApplicationRunner {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
private volatile boolean isStartupCompleted;
@ -151,12 +150,6 @@ public class AbstractConfiguration implements ApplicationContextAware, Applicati
return ApiConfig.getInstance().getUserKeyManager();
}
@Bean
@ConditionalOnMissingBean
SessionManager sessionManager() {
return ApiConfig.getInstance().getSessionManager();
}
@Bean
@ConditionalOnMissingBean
ParameterFormatter parameterFormatter() {

@ -1,244 +0,0 @@
package com.gitee.sop.gatewaycommon.session;
import org.springframework.util.Assert;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionContext;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import java.util.Vector;
/**
* @author tanghc
*/
@SuppressWarnings("deprecation")
public class ApiHttpSession implements HttpSession, Serializable {
private static final long serialVersionUID = 946272038219216222L;
private static final String ATTRIBUTE_NAME_MUST_NOT_BE_NULL = "Attribute name must not be null";
private final String id;
private final long creationTime = System.currentTimeMillis();
private int maxInactiveInterval;
private long lastAccessedTime = System.currentTimeMillis();
private final transient ServletContext servletContext;
private final transient Map<String, Object> attributes = new LinkedHashMap<>();
private boolean invalid = false;
private boolean isNew = true;
/**
* Create a new ApiHttpSession
*/
public ApiHttpSession() {
this(null);
}
/**
* Create a new ApiHttpSession.
*
* @param servletContext the ServletContext that the session runs in
*/
public ApiHttpSession(ServletContext servletContext) {
this(servletContext, null);
}
/**
* Create a new ApiHttpSession.
*
* @param servletContext the ServletContext that the session runs in
* @param id a unique identifier for this session
*/
public ApiHttpSession(ServletContext servletContext, String id) {
this.servletContext = servletContext;
this.id = this.buildId(id);
}
protected String buildId(String id) {
return (id != null ? id : UUID.randomUUID().toString().replace("-", "").toUpperCase());
}
@Override
public long getCreationTime() {
return this.creationTime;
}
@Override
public String getId() {
return this.id;
}
public void access() {
this.lastAccessedTime = System.currentTimeMillis();
this.isNew = false;
}
@Override
public long getLastAccessedTime() {
return this.lastAccessedTime;
}
@Override
public ServletContext getServletContext() {
return this.servletContext;
}
@Override
public void setMaxInactiveInterval(int interval) {
this.maxInactiveInterval = interval;
}
@Override
public int getMaxInactiveInterval() {
return this.maxInactiveInterval;
}
/**
* @return 返回HttpSessionContext已废弃不能使用
* @deprecated 已废弃不能使用
*/
@Override
@Deprecated
public HttpSessionContext getSessionContext() {
throw new UnsupportedOperationException("getSessionContext");
}
@Override
public Object getAttribute(String name) {
Assert.notNull(name, ATTRIBUTE_NAME_MUST_NOT_BE_NULL);
return this.attributes.get(name);
}
@Override
public Object getValue(String name) {
return getAttribute(name);
}
@Override
public Enumeration<String> getAttributeNames() {
return new Vector<String>(this.attributes.keySet()).elements();
}
@Override
public String[] getValueNames() {
return this.attributes.keySet().toArray(new String[this.attributes.size()]);
}
@Override
public void setAttribute(String name, Object value) {
Assert.notNull(name, ATTRIBUTE_NAME_MUST_NOT_BE_NULL);
if (value != null) {
this.attributes.put(name, value);
if (value instanceof HttpSessionBindingListener) {
((HttpSessionBindingListener) value).valueBound(new HttpSessionBindingEvent(this, name, value));
}
} else {
removeAttribute(name);
}
}
@Override
public void putValue(String name, Object value) {
setAttribute(name, value);
}
@Override
public void removeAttribute(String name) {
Assert.notNull(name, ATTRIBUTE_NAME_MUST_NOT_BE_NULL);
Object value = this.attributes.remove(name);
if (value instanceof HttpSessionBindingListener) {
((HttpSessionBindingListener) value).valueUnbound(new HttpSessionBindingEvent(this, name, value));
}
}
@Override
public void removeValue(String name) {
removeAttribute(name);
}
/**
* Clear all of this session's attributes.
*/
public void clearAttributes() {
for (Iterator<Map.Entry<String, Object>> it = this.attributes.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, Object> entry = it.next();
String name = entry.getKey();
Object value = entry.getValue();
it.remove();
if (value instanceof HttpSessionBindingListener) {
((HttpSessionBindingListener) value).valueUnbound(new HttpSessionBindingEvent(this, name, value));
}
}
}
@Override
public void invalidate() {
this.invalid = true;
clearAttributes();
}
public boolean isInvalid() {
return this.invalid;
}
public void setNew(boolean value) {
this.isNew = value;
}
@Override
public boolean isNew() {
return this.isNew;
}
/**
* Serialize the attributes of this session into an object that can be
* turned into a byte array with standard Java serialization.
*
* @return a representation of this session's serialized state
*/
public Serializable serializeState() {
HashMap<String, Serializable> state = new HashMap<>(16);
for (Iterator<Map.Entry<String, Object>> it = this.attributes.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, Object> entry = it.next();
String name = entry.getKey();
Object value = entry.getValue();
it.remove();
if (value instanceof Serializable) {
state.put(name, (Serializable) value);
} else {
// Not serializable... Servlet containers usually automatically
// unbind the attribute in this case.
if (value instanceof HttpSessionBindingListener) {
((HttpSessionBindingListener) value).valueUnbound(new HttpSessionBindingEvent(this, name, value));
}
}
}
return state;
}
/**
* Deserialize the attributes of this session from a state object created by
* {@link #serializeState()}.
*
* @param state a representation of this session's serialized state
*/
@SuppressWarnings("unchecked")
public void deserializeState(Serializable state) {
Assert.isTrue(state instanceof Map, "Serialized state needs to be of type [java.util.Map]");
this.attributes.putAll((Map<String, Object>) state);
}
}

@ -1,30 +0,0 @@
package com.gitee.sop.gatewaycommon.session;
import org.springframework.data.redis.connection.DefaultStringRedisConnection;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* @author tanghc
*/
public class ApiRedisTemplate extends RedisTemplate<String, Object> {
public ApiRedisTemplate() {
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
setKeySerializer(stringSerializer);
setHashKeySerializer(stringSerializer);
}
public ApiRedisTemplate(RedisConnectionFactory connectionFactory) {
this();
setConnectionFactory(connectionFactory);
afterPropertiesSet();
}
@Override
protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {
return new DefaultStringRedisConnection(connection);
}
}

@ -1,93 +0,0 @@
package com.gitee.sop.gatewaycommon.session;
import com.gitee.sop.gatewaycommon.message.ErrorEnum;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import java.util.concurrent.TimeUnit;
/**
* session管理,默认存放的是{@link ApiHttpSession}采用谷歌guava缓存实现
*
* @author tanghc
*/
public class ApiSessionManager implements SessionManager {
private static Logger logger = LoggerFactory.getLogger(ApiSessionManager.class);
private int sessionTimeout = 20;
private LoadingCache<String, HttpSession> cache;
public ApiSessionManager() {
cache = this.buildCache();
}
@Override
public HttpSession getSession(String sessionId) {
if (sessionId == null) {
return this.createSession(sessionId);
}
try {
return cache.get(sessionId);
} catch (Exception e) {
logger.error(e.getMessage(), e);
throw ErrorEnum.ISP_UNKNOWN_ERROR.getErrorMeta().getException();
}
}
/**
* 创建一个session
*
* @param sessionId 传null将返回一个新session
* @return 返回session
*/
protected HttpSession createSession(String sessionId) {
ServletContext servletContext = null;
HttpSession session = this.newSession(sessionId, servletContext);
session.setMaxInactiveInterval(getSessionTimeout());
this.cache.put(session.getId(), session);
return session;
}
/**
* 返回新的session实例
*
* @param sessionId
* @param servletContext
* @return 返回session
*/
protected HttpSession newSession(String sessionId, ServletContext servletContext) {
return new ApiHttpSession(servletContext, sessionId);
}
protected LoadingCache<String, HttpSession> buildCache() {
return CacheBuilder.newBuilder().expireAfterAccess(getSessionTimeout(), TimeUnit.MINUTES)
.build(new CacheLoader<String, HttpSession>() {
// 找不到sessionId对应的HttpSession时,进入这个方法
// 找不到就新建一个
@Override
public HttpSession load(String sessionId) throws Exception {
return createSession(sessionId);
}
});
}
public void setSessionTimeout(int sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
/**
* 过期时间,分钟,默认20分钟
*
* @return 返回过期时间
*/
public int getSessionTimeout() {
return sessionTimeout;
}
}

@ -1,269 +0,0 @@
package com.gitee.sop.gatewaycommon.session;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.Assert;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;
import java.io.Serializable;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* RedisHttpSession
*
* @author tanghc
*/
@SuppressWarnings("deprecation")
public class RedisHttpSession implements HttpSession, Serializable {
private static final long serialVersionUID = -8081963657251144855L;
private static final int SEC60 = 60;
private static final String SESSION_ATTR = "session_attr:";
private static final String CREATION_TIME = "creationTime";
private static final String LAST_ACCESSED_TIME = "lastAccessedTime";
private static final String MAX_INACTIVE_INTERVAL = "maxInactiveInterval";
/**
* 存入redis的key
*/
private String key;
/**
* sessionId
*/
private String id;
private transient ServletContext servletContext;
private transient RedisTemplate redisTemplate;
private RedisHttpSession() {
}
protected static String buildId(String id) {
return (id != null ? id : UUID.randomUUID().toString().replace("-", "").toUpperCase());
}
public static String buildKey(String keyPrefix, String sessionId) {
Assert.notNull(keyPrefix, "sessionPrefix不能为null");
return keyPrefix + sessionId;
}
/**
* 创建新的session
*
* @param servletContext servletContext
* @param sessionId sessionId
* @param sessionTimeout 过期时间单位秒
* @param redisTemplate redis客户端
* @param keyPrefix 存入的key前缀
* @return 返回session
*/
public static RedisHttpSession createNewSession(ServletContext servletContext, String sessionId, int sessionTimeout, RedisTemplate redisTemplate, String keyPrefix) {
Assert.notNull(redisTemplate, "redisTemplate can not null.");
Assert.notNull(sessionId, "sessionId can not null.");
Assert.notNull(keyPrefix, "keyPrefix can not null.");
RedisHttpSession redisHttpSession = new RedisHttpSession();
redisHttpSession.setId(sessionId);
redisHttpSession.setKey(buildKey(keyPrefix, sessionId));
redisHttpSession.setRedisTemplate(redisTemplate);
redisHttpSession.setServletContext(servletContext);
long creationTime = System.currentTimeMillis();
// 过期时间,分转换成秒
int maxInactiveInterval = sessionTimeout * SEC60;
redisHttpSession.setCreationTime(creationTime);
redisHttpSession.setLastAccessedTime(creationTime);
redisHttpSession.setMaxInactiveInterval(maxInactiveInterval);
redisHttpSession.refresh();
return redisHttpSession;
}
/**
* 创建已经存在的session,数据在redis里面
*
* @param sessionId sessionId
* @param servletContext servletContext
* @param redisTemplate redis客户端
* @param keyPrefix 存入的key前缀
* @return 返回session
*/
public static RedisHttpSession createExistSession(String sessionId, ServletContext servletContext, RedisTemplate redisTemplate, String keyPrefix) {
Assert.notNull(redisTemplate, "redisTemplate can not null.");
Assert.notNull(sessionId, "sessionId can not null.");
Assert.notNull(keyPrefix, "keyPrefix can not null.");
RedisHttpSession redisHttpSession = new RedisHttpSession();
redisHttpSession.setId(sessionId);
redisHttpSession.setKey(buildKey(keyPrefix, sessionId));
redisHttpSession.setRedisTemplate(redisTemplate);
redisHttpSession.setServletContext(servletContext);
redisHttpSession.refresh();
return redisHttpSession;
}
public void setId(String id) {
this.id = id;
}
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
public void setCreationTime(long creationTime) {
this.redisTemplate.opsForHash().put(key, CREATION_TIME, String.valueOf(creationTime));
}
@Override
public long getCreationTime() {
Object createTime = this.redisTemplate.opsForHash().get(key, CREATION_TIME);
return Long.valueOf(String.valueOf(createTime));
}
@Override
public String getId() {
return id;
}
@Override
public long getLastAccessedTime() {
Object lastAccessedTime = this.redisTemplate.opsForHash().get(key, LAST_ACCESSED_TIME);
return Long.valueOf(String.valueOf(lastAccessedTime));
}
@Override
public ServletContext getServletContext() {
return servletContext;
}
@Override
public void setMaxInactiveInterval(int interval) {
this.redisTemplate.opsForHash().put(key, MAX_INACTIVE_INTERVAL, String.valueOf(interval));
}
@Override
public int getMaxInactiveInterval() {
Object maxInactiveInterval = this.redisTemplate.opsForHash().get(key, MAX_INACTIVE_INTERVAL);
return Integer.valueOf(String.valueOf(maxInactiveInterval));
}
/**
* @return 返回HttpSessionContext已废弃不能使用
* @deprecated 已废弃始终返回null
*/
@Override
@Deprecated
public HttpSessionContext getSessionContext() {
return null;
}
@Override
public Object getAttribute(String name) {
return this.redisTemplate.opsForHash().get(key, SESSION_ATTR + name);
}
@Override
public Object getValue(String name) {
return getAttribute(name);
}
@Override
public Enumeration<String> getAttributeNames() {
return Collections.enumeration(getAttributeKeys());
}
private Set<String> getAttributeKeys() {
Set keys = this.redisTemplate.opsForHash().keys(key);
Set<String> attrNames = new HashSet<>();
for (Object key : keys) {
String k = String.valueOf(key);
if (k.startsWith(SESSION_ATTR)) {
attrNames.add(k.substring(SESSION_ATTR.length()));
}
}
return attrNames;
}
@Override
public String[] getValueNames() {
return getAttributeKeys().toArray(new String[0]);
}
@Override
public void setAttribute(String name, Object value) {
this.redisTemplate.opsForHash().put(key, SESSION_ATTR + name, value);
}
@Override
public void putValue(String name, Object value) {
setAttribute(name, value);
}
@Override
public void removeAttribute(String name) {
this.redisTemplate.opsForHash().delete(key, name);
}
@Override
public void removeValue(String name) {
removeAttribute(name);
}
@Override
public void invalidate() {
this.redisTemplate.delete(key);
}
@Override
public boolean isNew() {
return false;
}
/**
* update expireTime,accessTime
*/
public void refresh() {
// token更新过期时间
this.redisTemplate.expire(key, getMaxInactiveInterval(), TimeUnit.SECONDS);
// 设置访问时间
this.setLastAccessedTime(System.currentTimeMillis());
}
public void setLastAccessedTime(long lastAccessedTime) {
this.redisTemplate.opsForHash().put(key, LAST_ACCESSED_TIME, String.valueOf(lastAccessedTime));
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public boolean isInvalidated() {
return !this.redisTemplate.hasKey(key);
}
public void setRedisTemplate(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
}

@ -1,105 +0,0 @@
package com.gitee.sop.gatewaycommon.session;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.Assert;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import java.util.UUID;
/**
* SessionManager的redis实现使用redis管理session
*
* @author tanghc
*/
public class RedisSessionManager implements SessionManager {
private ApiRedisTemplate redisTemplate;
/**
* 过期时间30分钟
*/
private int sessionTimeout = 30;
/**
* 存入redis中key的前缀
*/
private String keyPrefix = "session:";
public RedisSessionManager(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {
Assert.notNull(redisTemplate, "RedisSessionManager中的redisTemplate不能为null");
this.redisTemplate = new ApiRedisTemplate(redisTemplate.getConnectionFactory());
}
@Override
public HttpSession getSession(String sessionId) {
return this.getSession(sessionId, this.keyPrefix);
}
public HttpSession getSession(String sessionId, String keyPrefix) {
if (this.hasKey(sessionId)) {
return RedisHttpSession.createExistSession(sessionId, getServletContext(), redisTemplate, keyPrefix);
} else {
sessionId = this.buildSessionId(sessionId);
return RedisHttpSession.createNewSession(getServletContext(), sessionId, this.getSessionTimeout(),
redisTemplate, keyPrefix);
}
}
/**
* 构建sessionId
*
* @param id
* @return 返回sessionid
*/
public String buildSessionId(String id) {
return (id != null ? id : UUID.randomUUID().toString().replace("-", "").toUpperCase());
}
public boolean hasKey(String sessionId) {
if (sessionId == null) {
return false;
} else {
String key = RedisHttpSession.buildKey(this.keyPrefix, sessionId);
return redisTemplate.hasKey(key);
}
}
public ServletContext getServletContext() {
return null;
}
public int getSessionTimeout() {
return sessionTimeout;
}
/**
* 设置session过期时间单位分钟
*
* @param sessionTimeout
*/
public void setSessionTimeout(int sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
public ApiRedisTemplate getRedisTemplate() {
return redisTemplate;
}
public void setRedisTemplate(ApiRedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
public String getKeyPrefix() {
return keyPrefix;
}
/**
* 设置存入redis中key的前缀默认为"session:"
*
* @param keyPrefix
*/
public void setKeyPrefix(String keyPrefix) {
this.keyPrefix = keyPrefix;
}
}

@ -1,20 +0,0 @@
package com.gitee.sop.gatewaycommon.session;
import javax.servlet.http.HttpSession;
/**
* session管理
*
* @author tanghc
*
*/
public interface SessionManager {
/**
* 根据sessionId获取session
*
* @param sessionId 客户端传过来的sessionId,为null时创建一个新session
* @return 返回session
*/
HttpSession getSession(String sessionId);
}

@ -26,7 +26,7 @@ spring.cloud.gateway.discovery.locator.enabled=true
mybatis.fill.com.gitee.fastmybatis.core.support.DateFillInsert=gmt_create
mybatis.fill.com.gitee.fastmybatis.core.support.DateFillUpdate=gmt_modified
# POST请求最大缓存,默认是256KB,即:262144
# POST请求最大缓存,默认是262144(256KB),即:256 * 1024
# 如果需要传输大文本可以把值设置高一点
spring.codec.max-in-memory-size=262144

Loading…
Cancel
Save