转载自:http://blog.csdn.net/u010497606/article/details/52935556
session会话在单台服务器下不会出现共享问题,现在应用部署方式都是分布式,或者集群部署,这样必然会面临一个问题,session共享。
session共享的解决方案也有很多,
一、web服务器的粘性请求,比如采用nginx请求分发,使用ip_hash这种负载均衡方式,客户端请求只会被分发到相同的后台server,这样可以避免session共享的问题。但是缺点也很明显
二、基于数据库存储(网站用户量大的情况下,频繁dml数据,对db压力大)
三、基于cookie存储(安全问题、虽然可以加密存储、但是我觉得永远不能将敏感数据放在客户端,不信任啊O(∩_∩)O哈哈~)
四、服务器内置的session复制域(比如was下提供session复制功能、但这个损耗服务器内存)
五、基于nosql(memcache、redis都可以)
![](//img-blog.csdn.net/20161027125058631?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://blog.csdn.net/u010497606/article/details/52935556)
http请求是无状态的
这里要引入一个概念sessionid,session对象当客户端首次访问时,创建一个新的session对象.并同时生成一个sessionId,并在此次响应中将sessionId以响应报文的方式些回客户端浏览器内存或以重写url方式送回客户端,来保持整个会话
也就是说客户端request请求时候,如果获取了session,就默认分配一个jessionid,然后通过response响应到客户端cookie,然后客户端下一次请求,默认会携带这个jessionid请求到服务端,服务端拿到这个jessionid来区分不同的客户端。
说清楚这些,就可以从sessionid入手了,要实现将session信息存入redis,总结了下大概是三点:
1.实现httpsession接口,重写我们需要用到的方法,比如set
get这些。。balabala一堆......
2.继承HttpServletRequestWrapper,这个类里面有getSession()方法,我们需要重写,来取自定义session
3.实现filter,用来拦截客户端请求,获取我们自定义的request,从而获得session
具体实现:
1.实现httpsession接口
- public class HttpSessionWrapper implements HttpSession {
- protected final Logger logger = LoggerFactory.getLogger(getClass());
- private String sid = "";
- private HttpServletRequest request;
- private HttpServletResponse response;
- private final long creationTime = System.currentTimeMillis();
- private final long lastAccessedTime = System.currentTimeMillis();
- private SessionMeta meta;
- public HttpSessionWrapper() {
- }
- public HttpSessionWrapper(String sid,SessionMeta meta, HttpServletRequest request,
- HttpServletResponse response) {
- this.sid=sid;
- this.request=request;
- this.response=response;
- this.meta=meta;
- }
- public Object getAttribute(String name) {
- logger.info(getClass()+"getAttribute(),name:"+name);
- Jedis jedis =null;
- Object obj =null;
- String jsonStr = null;
- try {
- jedis =JedisPoolStore.getInstance().getJedis(meta.getHost(), meta.getPort());
- jsonStr = jedis.get(name);
- if(jsonStr!=null||StringUtils.isNotEmpty(jsonStr)){
- jedis.expire(name, meta.getSeconds());
- obj =JSON.parseObject(jsonStr, User.class);
- }
- if (jedis != null) {
- JedisPoolStore.getInstance().returnJedis(jedis);
- }
- return obj;
- }
- catch (JSONException je) {
- logger.error(je.getMessage());
- if (null != jedis)
- JedisPoolStore.getInstance().returnJedis(jedis);
- return jsonStr;
- }
- catch (Exception e) {
- logger.error(e.getMessage());
- if (e instanceof JedisException) {
- if (null != jedis)
- JedisPoolStore.getInstance().returnBrokenJedis(jedis);
- } else {
- if (null != jedis)
- JedisPoolStore.getInstance().returnJedis(jedis);
- }
- throw new HttpSessionException(" session 异常 getAttribute() name:"+name);
- }
- }
- public void setAttribute(String name, Object value) {
- logger.info(getClass()+"setAttribute(),name:"+name);
- Jedis jedis =null;
- try {
- jedis =JedisPoolStore.getInstance().getJedis(meta.getHost(), meta.getPort());
- if(value instanceof String){
- String value_ =(String) value;
- jedis.set(name,value_);
- }else{
- jedis.set(name, JSON.toJSONString(value));
- }
-
- jedis.expire(name, meta.getSeconds());
- if (jedis != null) {
- JedisPoolStore.getInstance().returnJedis(jedis);
- }
- } catch (Exception e) {
- logger.error(e.getMessage());
- if (e instanceof JedisException) {
- if (null != jedis)
- JedisPoolStore.getInstance().returnBrokenJedis(jedis);
- } else {
- if (null != jedis)
- JedisPoolStore.getInstance().returnJedis(jedis);
- }
- throw new HttpSessionException(" session 异常 setAttribute() name:"+name+",value:"+value);
- }
-
- }
-
-
-
-
-
- public void invalidate() {
- logger.info(getClass()+"invalidate()");
- }
-
- public void removeAttribute(String name) {
- logger.info(getClass()+"removeAttribute(),name:"+name);
- if(StringUtils.isNotEmpty(name)){
- Jedis jedis =null;
- try {
- jedis =JedisPoolStore.getInstance().getJedis(meta.getHost(), meta.getPort());
- jedis.del(name);
- if (jedis != null) {
- JedisPoolStore.getInstance().returnJedis(jedis);
- }
- } catch (Exception e) {
- logger.error(e.getMessage());
- if (e instanceof JedisException) {
- if (null != jedis)
- JedisPoolStore.getInstance().returnBrokenJedis(jedis);
- } else {
- if (null != jedis)
- JedisPoolStore.getInstance().returnJedis(jedis);
- }
- throw new HttpSessionException(" session 异常 removeAttribute() name:"+name);
- }
- }
-
- }
-
-
-
-
-
- public Object getValue(String name) {
- return null;
- }
-
-
-
-
-
- public Enumeration getAttributeNames() {
- return null;
-
- }
-
-
-
-
-
- public String[] getValueNames() {
- return null;
- }
-
-
-
-
-
- public void putValue(String name, Object value) {
- }
-
-
-
-
-
- public void removeValue(String name) {
- }
-
- public long getCreationTime() {
- return creationTime;
- }
-
- public String getId() {
- logger.info(getClass()+"getId():"+sid);
- return sid;
- }
-
- public long getLastAccessedTime() {
- return lastAccessedTime;
- }
-
-
-
-
-
- public ServletContext getServletContext() {
- return null;
- }
-
-
-
-
-
- public void setMaxInactiveInterval(int interval) {
- }
-
-
-
-
-
- public int getMaxInactiveInterval() {
- return 0;
- }
-
-
-
-
-
- public HttpSessionContext getSessionContext() {
- return null;
- }
-
-
-
-
-
- public boolean isNew() {
- logger.info(getClass()+"isNew()");
- return false;
- }
- }
2.继承HttpServletRequestWrapper
-
-
-
-
-
- public class DefinedHttpServletRequestWrapper extends HttpServletRequestWrapper{
- protected final Logger logger = LoggerFactory.getLogger(getClass());
-
- private HttpSessionWrapper currentSession;
- private HttpServletRequest request;
- private HttpServletResponse response;
- private String sid = "";
- private SessionMeta meta;
-
- public DefinedHttpServletRequestWrapper(HttpServletRequest request) {
- super(request);
- }
-
- public DefinedHttpServletRequestWrapper(String sid, HttpServletRequest request) {
- super(request);
- this.sid = sid;
- }
-
- public DefinedHttpServletRequestWrapper(String sid, SessionMeta meta,HttpServletRequest request,
- HttpServletResponse response) {
- super(request);
- this.request = request;
- this.response = response;
- this.sid = sid;
- this.meta=meta;
- }
-
- @Override
- public HttpSession getSession(boolean create) {
- if(currentSession != null) {
- return currentSession;
- }
- if(!create) {
- return null;
- }
- currentSession = new HttpSessionWrapper(sid,meta, request, response);
- return currentSession;
- }
-
- @Override
- public HttpSession getSession() {
- return getSession(true);
- }
-
- }
3.实现filter
- public class SessionFilter implements Filter{
- protected final Logger logger = LoggerFactory.getLogger(getClass());
- private static SessionMeta meta = new SessionMeta();
- private static final String host ="host";
- private static final String port ="port";
- private static final String seconds="seconds";
-
- public void init(FilterConfig filterConfig) throws ServletException {
- logger.debug("init filterConfig info");
- meta.setHost(filterConfig.getInitParameter(host));
- meta.setPort(Integer.parseInt(filterConfig.getInitParameter(port)));
- meta.setSeconds(Integer.parseInt(filterConfig.getInitParameter(seconds)));
- }
-
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
-
- HttpServletRequest httpRequest = (HttpServletRequest) request;
- HttpServletResponse httpResponse = (HttpServletResponse) response;
- String sid = CookieHelper.findCookieInfo(httpRequest,CookieHelper.COOKIE_DOMAIN_NAME);
- if(StringUtils.isEmpty(sid) ){
- try {
- sid =CookieHelper.saveCookie(SessionId.doIds(), httpResponse);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- logger.info("JESSIONID:"+sid);
- chain.doFilter(new DefinedHttpServletRequestWrapper(sid,meta,httpRequest, httpResponse), response);
- }
-
- public void destroy() {
- }
-
- }
3.配置web.xml
- <!-- session过滤器 -->
- <filter>
- <filter-name>sessionFilter</filter-name>
- <filter-class>cn.session.filter.SessionFilter</filter-class>
- <init-param>
- <param-name>host</param-name>
- <param-value>10.1.193.1</param-value>
- </init-param>
- <init-param>
- <param-name>port</param-name>
- <param-value>6372</param-value>
- </init-param>
- <init-param>
- <param-name>seconds</param-name>
- <param-value>1800</param-value>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>sessionFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
第一次产生sessionid访问:
![](//img-blog.csdn.net/20161027125140865?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://blog.csdn.net/u010497606/article/details/52935556)
系统登录后存用户信息至redis,以及产生令牌:
![](//img-blog.csdn.net/20161027125237382?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://blog.csdn.net/u010497606/article/details/52935556)
![](//img-blog.csdn.net/20161027125327602?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
关于安全这块,因为不管登录系统与否,sessionid都会产生,这时候就会产生一个问题,因为cookie是可以被修改的,就会产生一个问题,撞session的分享。。。换成不同的sessionid去请求系统。。。总有一天会撞上。。
SO,我这边是这样处理的,
当登录成功之后,产生一个token令牌,产生规则的话自己定,一堆密钥比如系统名字+sessionid+userid+固定字符,产生一个加密的字符串,放入cookie。
这样当我们获取当前登录用户时,解密token,获取sessionid,然后取redis用户信息。。(切记这里不要直接通过sessionid取用户信息,有风险!!!)
用户没有登录成功,自然也没有这个令牌。。。
这里又有另外一个问题,用户如果禁用cookie呢????? so what..... 下次再说这个。。。
水平有限,如果你有更好的方式,请联系我,交流................................tks!!!!
- public class HttpSessionWrapper implements HttpSession {
- protected final Logger logger = LoggerFactory.getLogger(getClass());
- private String sid = "";
- private HttpServletRequest request;
- private HttpServletResponse response;
- private final long creationTime = System.currentTimeMillis();
- private final long lastAccessedTime = System.currentTimeMillis();
- private SessionMeta meta;
- public HttpSessionWrapper() {
- }
- public HttpSessionWrapper(String sid,SessionMeta meta, HttpServletRequest request,
- HttpServletResponse response) {
- this.sid=sid;
- this.request=request;
- this.response=response;
- this.meta=meta;
- }
- public Object getAttribute(String name) {
- logger.info(getClass()+"getAttribute(),name:"+name);
- Jedis jedis =null;
- Object obj =null;
- String jsonStr = null;
- try {
- jedis =JedisPoolStore.getInstance().getJedis(meta.getHost(), meta.getPort());
- jsonStr = jedis.get(name);
- if(jsonStr!=null||StringUtils.isNotEmpty(jsonStr)){
- jedis.expire(name, meta.getSeconds());
- obj =JSON.parseObject(jsonStr, User.class);
- }
- if (jedis != null) {
- JedisPoolStore.getInstance().returnJedis(jedis);
- }
- return obj;
- }
- catch (JSONException je) {
- logger.error(je.getMessage());
- if (null != jedis)
- JedisPoolStore.getInstance().returnJedis(jedis);
- return jsonStr;
- }
- catch (Exception e) {
- logger.error(e.getMessage());
- if (e instanceof JedisException) {
- if (null != jedis)
- JedisPoolStore.getInstance().returnBrokenJedis(jedis);
- } else {
- if (null != jedis)
- JedisPoolStore.getInstance().returnJedis(jedis);
- }
- throw new HttpSessionException(" session 异常 getAttribute() name:"+name);
- }
- }
- public void setAttribute(String name, Object value) {
- logger.info(getClass()+"setAttribute(),name:"+name);
- Jedis jedis =null;
- try {
- jedis =JedisPoolStore.getInstance().getJedis(meta.getHost(), meta.getPort());
- if(value instanceof String){
- String value_ =(String) value;
- jedis.set(name,value_);
- }else{
- jedis.set(name, JSON.toJSONString(value));
- }
-
- jedis.expire(name, meta.getSeconds());
- if (jedis != null) {
- JedisPoolStore.getInstance().returnJedis(jedis);
- }
- } catch (Exception e) {
- logger.error(e.getMessage());
- if (e instanceof JedisException) {
- if (null != jedis)
- JedisPoolStore.getInstance().returnBrokenJedis(jedis);
- } else {
- if (null != jedis)
- JedisPoolStore.getInstance().returnJedis(jedis);
- }
- throw new HttpSessionException(" session 异常 setAttribute() name:"+name+",value:"+value);
- }
-
- }
-
-
-
-
-
- public void invalidate() {
- logger.info(getClass()+"invalidate()");
- }
-
- public void removeAttribute(String name) {
- logger.info(getClass()+"removeAttribute(),name:"+name);
- if(StringUtils.isNotEmpty(name)){
- Jedis jedis =null;
- try {
- jedis =JedisPoolStore.getInstance().getJedis(meta.getHost(), meta.getPort());
- jedis.del(name);
- if (jedis != null) {
- JedisPoolStore.getInstance().returnJedis(jedis);
- }
- } catch (Exception e) {
- logger.error(e.getMessage());
- if (e instanceof JedisException) {
- if (null != jedis)
- JedisPoolStore.getInstance().returnBrokenJedis(jedis);
- } else {
- if (null != jedis)
- JedisPoolStore.getInstance().returnJedis(jedis);
- }
- throw new HttpSessionException(" session 异常 removeAttribute() name:"+name);
- }
- }
-
- }
-
-
-
-
-
- public Object getValue(String name) {
- return null;
- }
-
-
-
-
-
- public Enumeration getAttributeNames() {
- return null;
-
- }
-
-
-
-
-
- public String[] getValueNames() {
- return null;
- }
-
-
-
-
-
- public void putValue(String name, Object value) {
- }
-
-
-
-
-
- public void removeValue(String name) {
- }
-
- public long getCreationTime() {
- return creationTime;
- }
-
- public String getId() {
- logger.info(getClass()+"getId():"+sid);
- return sid;
- }
-
- public long getLastAccessedTime() {
- return lastAccessedTime;
- }
-
-
-
-
-
- public ServletContext getServletContext() {
- return null;
- }
-
-
-
-
-
- public void setMaxInactiveInterval(int interval) {
- }
-
-
-
-
-
- public int getMaxInactiveInterval() {
- return 0;
- }
-
-
-
-
-
- public HttpSessionContext getSessionContext() {
- return null;
- }
-
-
-
-
-
- public boolean isNew() {
- logger.info(getClass()+"isNew()");
- return false;
- }
- }
2.继承HttpServletRequestWrapper
-
-
-
-
-
- public class DefinedHttpServletRequestWrapper extends HttpServletRequestWrapper{
- protected final Logger logger = LoggerFactory.getLogger(getClass());
-
- private HttpSessionWrapper currentSession;
- private HttpServletRequest request;
- private HttpServletResponse response;
- private String sid = "";
- private SessionMeta meta;
-
- public DefinedHttpServletRequestWrapper(HttpServletRequest request) {
- super(request);
- }
-
- public DefinedHttpServletRequestWrapper(String sid, HttpServletRequest request) {
- super(request);
- this.sid = sid;
- }
-
- public DefinedHttpServletRequestWrapper(String sid, SessionMeta meta,HttpServletRequest request,
- HttpServletResponse response) {
- super(request);
- this.request = request;
- this.response = response;
- this.sid = sid;
- this.meta=meta;
- }
-
- @Override
- public HttpSession getSession(boolean create) {
- if(currentSession != null) {
- return currentSession;
- }
- if(!create) {
- return null;
- }
- currentSession = new HttpSessionWrapper(sid,meta, request, response);
- return currentSession;
- }
-
- @Override
- public HttpSession getSession() {
- return getSession(true);
- }
-
- }
3.实现filter
- public class SessionFilter implements Filter{
- protected final Logger logger = LoggerFactory.getLogger(getClass());
- private static SessionMeta meta = new SessionMeta();
- private static final String host ="host";
- private static final String port ="port";
- private static final String seconds="seconds";
-
- public void init(FilterConfig filterConfig) throws ServletException {
- logger.debug("init filterConfig info");
- meta.setHost(filterConfig.getInitParameter(host));
- meta.setPort(Integer.parseInt(filterConfig.getInitParameter(port)));
- meta.setSeconds(Integer.parseInt(filterConfig.getInitParameter(seconds)));
- }
-
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
-
- HttpServletRequest httpRequest = (HttpServletRequest) request;
- HttpServletResponse httpResponse = (HttpServletResponse) response;
- String sid = CookieHelper.findCookieInfo(httpRequest,CookieHelper.COOKIE_DOMAIN_NAME);
- if(StringUtils.isEmpty(sid) ){
- try {
- sid =CookieHelper.saveCookie(SessionId.doIds(), httpResponse);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- logger.info("JESSIONID:"+sid);
- chain.doFilter(new DefinedHttpServletRequestWrapper(sid,meta,httpRequest, httpResponse), response);
- }
-
- public void destroy() {
- }
-
- }
3.配置web.xml
- <!-- session过滤器 -->
- <filter>
- <filter-name>sessionFilter</filter-name>
- <filter-class>cn.session.filter.SessionFilter</filter-class>
- <init-param>
- <param-name>host</param-name>
- <param-value>10.1.193.1</param-value>
- </init-param>
- <init-param>
- <param-name>port</param-name>
- <param-value>6372</param-value>
- </init-param>
- <init-param>
- <param-name>seconds</param-name>
- <param-value>1800</param-value>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>sessionFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
第一次产生sessionid访问:
![](//img-blog.csdn.net/20161027125140865?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://blog.csdn.net/u010497606/article/details/52935556)
系统登录后存用户信息至redis,以及产生令牌:
![](//img-blog.csdn.net/20161027125237382?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://blog.csdn.net/u010497606/article/details/52935556)
![](//img-blog.csdn.net/20161027125327602?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
关于安全这块,因为不管登录系统与否,sessionid都会产生,这时候就会产生一个问题,因为cookie是可以被修改的,就会产生一个问题,撞session的分享。。。换成不同的sessionid去请求系统。。。总有一天会撞上。。
SO,我这边是这样处理的,
当登录成功之后,产生一个token令牌,产生规则的话自己定,一堆密钥比如系统名字+sessionid+userid+固定字符,产生一个加密的字符串,放入cookie。
这样当我们获取当前登录用户时,解密token,获取sessionid,然后取redis用户信息。。(切记这里不要直接通过sessionid取用户信息,有风险!!!)
用户没有登录成功,自然也没有这个令牌。。。
这里又有另外一个问题,用户如果禁用cookie呢?????
so what..... 下次再说这个。。。
水平有限,如果你有更好的方式,请联系我,交流................................tks!!!!