牛骨文教育服务平台(让学习变的简单)
博文笔记

分布式环境下用redis模拟session

创建时间:2017-12-21 投稿人: 浏览次数:410

首先为什么使用redis?

因为分布式有不同服务器的缘故,如果你安照一般方式存储session,那么你的session会保存在某一台服务器上,如果你的下一个请求并不是访问这台服务器,那么会发生读取不到session的情况

redis存储的实现方案:

第一种 是使用容器拓展来实现,一般都是通过容器插件来实现,例如基于Tomcat的tomcat-redis-session-manager,基于Jetty的jetty-session-redis等等。好处是对项目来说是透明的,无需更改代码,但是目前还不支持Tomcat8。个人觉得由于过于依赖容器,,一旦更换容器或者容器升级,那又得重新来过。而且代码并不在项目中,对于开发者的维护也是个麻烦。

第二种 是自定义会话管理的工具类,这样的话灵活性很大,可以根据自身需求来实现,但是需要额外的开发时间

第三种是使用框架的会话管理工具,例如spring-session,shiro等,可以理解是替换了servlet那一套会话管理,不依赖容器,不用改动代码。如果采用spring-session的话,使用的是spring-data-redis那一套连接池,prefect,不过前提是你得用spring框架。至于shiro,那是一个十分成熟,强大易用的安全框架,学习成本比spring-session来的要多一些。

下面我们介绍一下第二种方式的实现

要注意的是为什么前端用ajax的方式登录,因为把模拟的session信息用存到redis后,需要在本地存入userId和token来作为用户的标识,通过这个标识去redis里验证该用户是否登录,从而获取redis中的用户登录信息,但是分布式中多个系统对应多个domain,所以login模块生成的userId和token要想每个系统都用,必须每个系统都生成自己的cookie信息,java端无法为每个系统生成一份cookie所以只能在前端用iframe的方式为每个系统生成一份cookie

下面是详细代码

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:context="http://www.springframework.org/schema/context"
    xmlns:mongo="http://www.springframework.org/schema/data/mongo" xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/context   
          http://www.springframework.org/schema/context/spring-context.xsd   
          http://www.springframework.org/schema/data/mongo   
          http://www.springframework.org/schema/data/mongo/spring-mongo-1.7.xsd   
          http://www.springframework.org/schema/beans   
          http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- redis缓存部分 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="${redis.maxIdle}" />
        <property name="maxTotal" value="${redis.maxTotal}" />
        <property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean>

    <bean id="redisConnectionFactory"
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
        p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"
        p:pool-config-ref="poolConfig" />

    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="redisConnectionFactory" />
    </bean>
    <!--加载redis -->
    <bean id="redisService" class="com.maigangle.b2b.common.redis.RedisSpringServiceImpl">
        <!-- 控制redis开关 -->
        <property name="isUse" value="true"></property>
    </bean>
</beans>

RedisSpringServiceImpl.java

package com.maigangle.b2b.common.redis;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;

import com.alibaba.fastjson.JSON;
import com.maigangle.b2b.common.exception.CommonException;

/**
 * redis接口实现
 * 
 * @author 
 * @since 
 * @version 1.0
 *
 */
public class RedisSpringServiceImpl implements RedisSpringService {
    private static String redisCode = "utf-8";
    private boolean isUse; // redis开关

    private byte[] getBytes(String str) {
        try {
            return str.getBytes(redisCode);
        } catch (UnsupportedEncodingException e) {
            return str.getBytes();
        }
    }

    public boolean isUse() {
        return isUse;
    }

    public void setIsUse(boolean isUse) {
        this.isUse = isUse;
    }

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public void pub(String channel, String param) {
        if (!isUse)
            return;
        redisTemplate.convertAndSend(channel, param);
    }

    /**
     * @param key
     */
    public Long del(final String... keys) {
        if (!isUse)
            return null;
        try {
            long re = redisTemplate.execute(new RedisCallback<Long>() {
                public Long doInRedis(RedisConnection connection) throws DataAccessException {
                    long result = 0;
                    for (int i = 0; i < keys.length; i++) {
                        result = connection.del(keys[i].getBytes());
                        result++;
                    }
                    return result;
                }
            });
            return re;
        } catch (Exception e) {
            return null;
        }

    }

    /**
     * @param key
     * @param value
     * @param liveTime
     */
    public void set(final byte[] key, final byte[] value, final long liveTime) {
        if (!isUse)
            return;
        try {
            redisTemplate.execute(new RedisCallback<Long>() {
                public Long doInRedis(RedisConnection connection) throws DataAccessException {
                    connection.set(key, value);
                    if (liveTime > 0) {
                        connection.expire(key, liveTime);
                    }
                    return 1L;
                }
            });
        } catch (Exception e) {
            closeSwitch(e);
            e.printStackTrace();
        }
    }

    /**
     * @param key
     * @param value
     * @param liveTime
     */
    public void set(String key, String value, long liveTime) {
        this.set(getBytes(key), getBytes(value), liveTime);
    }

    /**
     * @param key
     * @param liveTime
     */
    public boolean expire(String key, long liveTime) {
        if (!isUse)
            return false;
        try {
            return redisTemplate.execute(new RedisCallback<Boolean>() {
                public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                    return connection.expire(key.getBytes(), liveTime);
                }
            });
        } catch (Exception e) {
            closeSwitch(e);
            e.printStackTrace();
            return false;
        }
    }

    /**
     * @param key
     * @param value
     */
    public void set(String key, String value) {
        this.set(key, value, 0L);
    }

    /**
     * @param key
     * @param value
     */
    public void set(byte[] key, byte[] value) {
        this.set(key, value, 0L);
    }

    /**
     * @param key
     * @param value
     */
    public void set(String key, byte[] value) {
        this.set(getBytes(key), value, 0L);
    }

    /**
     * 
     */
    @Override
    public void setOjb(String key, Object value, long time) {
        this.set(getBytes(key), getBytes(JSON.toJSONString(value)), time);
    }

    /**
     * @param key
     * @return
     */
    public String get(final String key) {
        if (!isUse)
            return null;
        try {
            return redisTemplate.execute(new RedisCallback<String>() {
                public String doInRedis(RedisConnection connection) throws DataAccessException {
                    try {
                        byte[] bytes = connection.get(getBytes(key));
                        if (bytes == null || bytes.length == 0) {
                            return null;
                        }
                        return new String(bytes, redisCode);
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    } catch (Exception e1) {
                        e1.printStackTrace();
                        return null;
                    }
                    return "";
                }
            });
        } catch (Exception e) {
            closeSwitch(e);
            e.printStackTrace();
            return null;
        }
    }

    public byte[] get4byte(final String key) {
        if (!isUse)
            return null;
        try {
            return redisTemplate.execute(new RedisCallback<byte[]>() {
                public byte[] doInRedis(RedisConnection connection) throws DataAccessException {
                    try {
                        return connection.get(getBytes(key));
                    } catch (Exception e1) {
                        e1.printStackTrace();
                        return null;
                    }
                }
            });
        } catch (Exception e) {
            closeSwitch(e);
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public <T> T getObj(String key, Class<T> elementType) {
        String jsonString = this.get(key);
        T obj;
        obj = JSON.parseObject(jsonString, elementType);
        if (obj == null) {
            try {
                obj = elementType.newInstance();// 防止空指针异常
            } catch (InstantiationException | IllegalAccessException e) {
                throw new CommonException("get redis error:", e);
            }
        }
        return obj;
    }

    /**
     * @param pattern
     * @return
     */
    public void Setkeys(String pattern) {
        if (!isUse)
            return;
        try {
            redisTemplate.keys(pattern);
        } catch (Exception e) {
            closeSwitch(e);
            e.printStackTrace();
        }

    }

    /**
     * @param key
     * @return
     */
    public boolean exists(final String key) {
        if (!isUse)
            return false;
        try {
            return redisTemplate.execute(new RedisCallback<Boolean>() {
                public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                    return connection.exists(getBytes(key));
                }
            });
        } catch (Exception e) {
            closeSwitch(e);
            e.printStackTrace();
            return false;
        }
    }

    /**
     * @return
     */
    // public String flushDB() {
    // if(!isUse) return null;
    // return redisTemplate.execute(new RedisCallback<String>() {
    // public String doInRedis(RedisConnection connection) throws
    // DataAccessException {
    // connection.flushDb();
    // return "ok";
    // }
    // });
    // }
    public boolean flushDB() {
        if (!isUse)
            return false;
        try {
            return redisTemplate.execute(new RedisCallback<Boolean>() {
                public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                    connection.flushDb();
                    return true;
                }
            });
        } catch (Exception e) {
            closeSwitch(e);
            e.printStackTrace();
            return false;
        }
    }

    /**
     * @return
     */
    public long dbSize() {
        if (!isUse)
            return 0;
        try {
            return redisTemplate.execute(new RedisCallback<Long>() {
                public Long doInRedis(RedisConnection connection) throws DataAccessException {
                    return connection.dbSize();
                }
            });
        } catch (Exception e) {
            closeSwitch(e);
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * @return
     */
    public String ping() {
        if (!isUse)
            return null;
        try {
            return redisTemplate.execute(new RedisCallback<String>() {
                public String doInRedis(RedisConnection connection) throws DataAccessException {
                    return connection.ping();
                }
            });
        } catch (Exception e) {
            closeSwitch(e);
            e.printStackTrace();
            return null;
        }
    }

    private void closeSwitch(Exception e) {
        if (e instanceof RedisConnectionFailureException) {
            this.isUse = false;
        }
    }

    /**
     * submit check token
     * 
     * @param token
     * @return
     */
    public boolean checkToken(String token) {
        if (StringUtils.isBlank(token)) {
            return false;
        }
        Object tk = this.get(token);
        if (tk != null) {
            this.del(token);
            return true;
        }
        return false;
    }

    @Override
    public void setHm(String key, Map<String, String> map, long liveTime) {
        if (!isUse)
            return;
        final Map<byte[], byte[]> hashes = new LinkedHashMap<byte[], byte[]>(map.size());
        for (Map.Entry<String, String> entry : map.entrySet()) {
            hashes.put(getBytes(entry.getKey()), getBytes(entry.getValue()));
        }
        redisTemplate.execute(new RedisCallback<Object>() {

            public Object doInRedis(RedisConnection connection) {
                connection.hMSet(getBytes(key), hashes);
                if (liveTime > 0) {
                    connection.expire(getBytes(key), liveTime);
                }
                return null;
            }
        }, true);
    }

    @Override
    public Map<String, String> getHm(String key) {
        final byte[] rawKey = getBytes(key);
        Map<byte[], byte[]> entries = redisTemplate.execute(new RedisCallback<Map<byte[], byte[]>>() {
            public Map<byte[], byte[]> doInRedis(RedisConnection connection) {
                return connection.hGetAll(rawKey);
            }
        }, true);
        Map<String, String> map = new LinkedHashMap<String, String>(entries.size());
        for (Map.Entry<byte[], byte[]> entry : entries.entrySet()) {
            try {
                map.put(new String(entry.getKey(), redisCode), new String(entry.getValue(), redisCode));
            } catch (UnsupportedEncodingException e) {
                return new HashMap<String, String>();
            }
        }
        return map;
    }

    @Override
    public void setList(String key, List<String> list, long liveTime) {
        if (!isUse)
            return;
        final List<byte[]> listes = new ArrayList<byte[]>(list.size());
        for (String value : list) {
            listes.add(getBytes(value));
        }
        redisTemplate.execute(new RedisCallback<Object>() {
            public Object doInRedis(RedisConnection connection) {
                for (byte[] bs : listes) {
                    connection.rPush(getBytes(key), bs);
                }
                if (liveTime > 0) {
                    connection.expire(getBytes(key), liveTime);
                }
                return null;
            }
        }, true);
    }

    @Override
    public List<String> getList(String key) {
        final byte[] rawKey = getBytes(key);
        List<byte[]> entries = redisTemplate.execute(new RedisCallback<List<byte[]>>() {
            public List<byte[]> doInRedis(RedisConnection connection) {
                return connection.lRange(rawKey, 0, -1);
            }
        }, true);
        List<String> list = new ArrayList<String>(entries.size());
        for (byte[] entry : entries) {
            try {
                list.add(new String(entry, redisCode));
            } catch (UnsupportedEncodingException e) {
                return new ArrayList<String>();
            }
        }
        return list;
    }
}

接口: RedisSpringService.java

package com.maigangle.b2b.common.redis;

import java.util.List;
import java.util.Map;

/**
 * redis对外提供服务接口,如需使用请先注入(基于spring)
 * 
 * @author 朱晗
 * @since 2016年11月28日 上午8:41:45
 * @version 1.0
 *
 */
public interface RedisSpringService {
    /**
     * 发布消息
     * 
     */
    public abstract void pub(String channel, String param);

    /**
     * 通过key删除
     * 
     * @param key
     */
    public abstract Long del(String... keys);

    /**
     * 添加key value 并且设置存活时间(byte)
     * 
     * @param key
     * @param value
     * @param liveTime
     */
    public abstract void set(byte[] key, byte[] value, long liveTime);

    /**
     * 添加key value 并且设置存活时间
     * 
     * @param key
     * @param value
     * @param liveTime
     *            单位秒
     */
    public abstract void set(String key, String value, long liveTime);

    /**
     * 设置key过期时间
     * 
     * @param key
     * @param liveTime
     * @return
     */
    public abstract boolean expire(String key, long liveTime);

    /**
     * 添加key value
     * 
     * @param key
     * @param value
     */
    public abstract void set(String key, String value);

    /**
     * 添加key value
     * 
     * @param key
     * @param value
     */
    public abstract void set(String key, byte[] value);

    /**
     * 添加key value (字节)(序列化)
     * 
     * @param key
     * @param value
     */
    public abstract void set(byte[] key, byte[] value);

    /**
     * 保存对象
     * 
     * @param key
     * @param value
     */
    public abstract void setOjb(final String key, Object value, long time);

    /**
     * 获取redis value (String)
     * 
     * @param key
     * @return
     */
    public abstract String get(String key);

    public abstract byte[] get4byte(String key);

    /**
     * 得到对象
     * 
     * @param key
     * @param elementType
     * @return
     */
    public abstract <T> T getObj(final String key, Class<T> elementType);

    /**
     * 通过正则匹配keys
     * 
     * @param pattern
     * @return
     */
    public abstract void Setkeys(String pattern);

    /**
     * 检查key是否已经存在
     * 
     * @param key
     * @return
     */
    public abstract boolean exists(String key);

    /**
     * 清空redis 所有数据
     * 
     * @return
     */
    // public abstract String flushDB();
    public abstract boolean flushDB();

    /**
     * 查看redis里有多少数据
     */
    public abstract long dbSize();

    /**
     * 检查是否连接成功
     * 
     * @return
     */
    public abstract String ping();

    /**
     * submit check token
     * 
     * @param token
     * @return
     */
    public boolean checkToken(String token);

    /**
     * 
     * @author 朱晗
     * @since 2017年6月7日 上午8:45:55
     * @param key
     * @param map
     * @param liveTime
     */
    public void setHm(String key, Map<String, String> map, long liveTime);

    /**
     * 
     * @author 朱晗
     * @since 2017年6月7日 上午8:45:58
     * @param key
     * @return
     */
    public Map<String, String> getHm(String key);

    /**
     * 
     * @author 朱晗
     * @since 2017年6月7日 上午8:46:50
     * @param key
     * @param list
     * @param liveTime
     */
    public void setList(String key, List<String> list, long liveTime);

    /**
     * 
     * @author 朱晗
     * @since 2017年6月7日 上午8:46:55
     * @param key
     * @return
     */
    public List<String> getList(String key);
}

前端:

login.js

$("#loginIn").click(function(event) { 
        var $this = $(this);
        var acc = $("#account").val();
        var pw = $("#password").val();
        var loadUrl = util.get("redirectURL");
        var loginValid = $("#loginForm").valid();
        var setHtml = "";
        var loginUrl = "";

        // 如果返回false 设置为空
        if (loadUrl === false) {
            loadUrl = "";
        }

        if(loginValid) {
            $this.text("正在登录...");
            $this.attr("disabled", true);

            $.ajax({
                url: apiPath + "/auth/ajaxDoLogin",
                type: "post",
                data: {
                    account: acc,
                    passwd: pw,
                    redirectURL: loadUrl
                },
                success: function(data) {
                    if (data.isVaild) {
                        if(data.role === "A"){
                            setHtml += "<iframe src="" + gangUrlBase + "/api/common/setCookie?_it_=" + data._it_ + "&_token_="+ data._token_ +""></iframe>";
                            setHtml += "<iframe src="" + payUrlBase + "/api/common/setCookie?_it_=" + data._it_ + "&_token_="+ data._token_  + ""></iframe>";
                            setHtml += "<iframe src="" + orderUrlBase + "/api/common/setCookie?_it_=" + data._it_ + "&_token_="+ data._token_  + ""></iframe>";
                            setHtml += "<iframe src="" + homeUrlBase + "/api/common/setCookie?_it_=" + data._it_ + "&_token_="+ data._token_  + ""></iframe>";
                            setHtml += "<iframe src="" + cartUrlBase + "/api/common/setCookie?_it_=" + data._it_ + "&_token_="+ data._token_  + ""></iframe>";
                            setHtml += "<iframe src="" + cangkuUrlBase + "/api/common/setCookie?_it_=" + data._it_ + "&_token_="+ data._token_  + ""></iframe>";
                            setHtml += "<iframe src="" + fundUrlBase + "/api/common/setCookie?_it_=" + data._it_ + "&_token_="+ data._token_  + ""></iframe>";
                            setHtml += "<iframe src="" + regUrlBase + "/api/common/setCookie?_it_=" + data._it_ + "&_token_="+ data._token_  + ""></iframe>";
                            setHtml += "<iframe src="" + baikeUrlBase + "/api/common/setCookie?_it_=" + data._it_ + "&_token_="+ data._token_  + ""></iframe>";
                            setHtml += "<iframe src="" + helpUrlBase + "/api/common/setCookie?_it_=" + data._it_ + "&_token_="+ data._token_  + ""></iframe>";
                            setHtml += "<iframe src="" + indexUrlBase + "/api/common/setCookie?_it_=" + data._it_ + "&_token_="+ data._token_  + ""></iframe>";
                        }else if(data.role === "B"){
                             setHtml += "<iframe src="" + cangkuUrlBase + "/api/common/setCookie?_it_=" + data._it_ + "&_token_="+ data._token_  + ""></iframe>";
                        }else if(data.role === "C"){
                             setHtml += "<iframe src="" + mcUrlBase + "/api/common/setCookie?_it_=" + data._it_ + "&_token_="+ data._token_  + ""></iframe>";
                        }
                        if(data.isNotBindPhone) {
                            window.location.href = data.redirectURL + "?firmId=" + data.firmId;
                        } else {
                            // 添加iframe执行写入cookie
                            $("#setCookieView").html(setHtml);
                            setTimeout(function() {
                               window.location.href = data.redirectURL;
                            }, 2000);
                        }
                    } else {
                        $("#accError").show();
                        $("#accError").text(data.msg);
                        $this.text("我同意交易规则,登录");
                        $this.attr("disabled", false);
                    }
                },
                error: function(msg){
                    $("#accError").show();
                    $("#accError").text("登录失败!");
                    $this.text("我同意交易规则,登录");
                    $this.attr("disabled", false);
                }
            });
        }
    });

后端java代码

@RequestMapping(value = "/ajaxDoLogin")
    @ResponseBody
    public Map<String, Object> ajaxDoLogin( HttpServletRequest request,
                                            HttpServletResponse response,
                                            String account,
                                            String passwd,
                                            String redirectURL) {
        String logBatch = LogBatchUtil.getLogUUID(EnumMonitorLog.LOGSYSTEM_LOGIN.getKey());
        Map<String, Object> resultMap = new HashMap<String, Object>();
        try {
            super.logInfo(  request,
                            logBatch,
                            "登录",
                            "进入登录相关数据,account:" + account + ",redirectURL:" + redirectURL,
                            EnumMonitorLog.LOGSYSTEM_LOGIN.getKey());
            account = account.replaceAll(" ", "");
            // 登录验证
            Map<String, Object> vaildMap = validateLogin(request, account, passwd);
            boolean isVaild = (boolean) vaildMap.get("isVaild");
            if (!isVaild) {
                return vaildMap;
            }
            // 手机登录/交易商登录
            if (loginService.countByMobile(account) == 0) {
                resultMap = firmIdLogin(request, response, logBatch, account, passwd, redirectURL);// 账号为交易号
            } else {
                resultMap = mobileLogin(request, response, logBatch, account, passwd, redirectURL);// 账号为手机号码
            }
            return resultMap;
        }
        catch (Exception e) {
            e.printStackTrace();
            super.logError( request,
                            logBatch,
                            "账号为:" + account + "会员登录失败",
                            "交易商ID为:" + getFirmId(request) + "错误信息为:" + ExceptionUtils.getStackTrace(e),
                            Boolean.getBoolean(redisSpringService.get(EnumMonitorLog.LOG_NOTIFY_SWITCH.getKey())),
                            EnumMonitorLog.LOGSYSTEM_LOGIN.getKey());
            resultMap.put("msg", "非法登录");
            resultMap.put("isVaild", false);
            return resultMap;
        }
    }



private Map<String, Object> firmIdLogin(HttpServletRequest request,
                                            HttpServletResponse response,
                                            String logBatch,
                                            String account,
                                            String passwd,
                                            String redirectURL) {
        AcntUserBasic acntUserBasic = null;
        Map<String, Object> resultMap = null;
        // 账号为交易号
        if (!loginApi(request, logBatch, account, passwd)) {
            return this.setLoginError(account, passwd);
        }
        acntUserBasic = loginService.selectByFirmId(account);
        if (acntUserBasic != null && !StringUtils.equals(acntUserBasic.getIsLock(), IsLockEnum.IS_LOCK_N.getKey())) {
            return this.setLockError(account, passwd, "登录帐号" + account + IsLockEnum.getLockInfo(acntUserBasic.getIsLock()));
        }
        // 用户基本信息不存在或手机号为空(后台新增用户)
        if (acntUserBasic == null || StringUtils.isBlank(acntUserBasic.getMobile())) {
            // 绑定手机号
            resultMap = new HashMap<String, Object>();
            resultMap.put("isVaild", true);
            resultMap.put("isNotBindPhone", true);
            resultMap.put("redirectURL", super.getUrl(AuthUrlConstant.LOGIN_URL) + "/auth/bindPhoneFirst");
            resultMap.put("firmId", account);
            return resultMap;
        }
        super.logInfo(request, logBatch, "会员登录", "通过pc端进行登录认证," + "账号为:" + account + "会员认证成功", EnumMonitorLog.LOGSYSTEM_LOGIN.getKey());
        String token = UUIDUtil.getRandomUUID();// 登录token
        setLoginInfo(request, response, acntUserBasic, logBatch, account, token);
        resultMap = redirectToURL(acntUserBasic.getUserId(), acntUserBasic.getUserRole(), redirectURL, token);
        resultMap.put("role", acntUserBasic.getUserRole());//返回用户角色
        return resultMap;
    }


private void setLoginInfo(  HttpServletRequest request,
                                HttpServletResponse response,
                                AcntUserBasic acntUserBasic,
                                String logBatch,
                                String account,
                                String token) {
        super.logInfo(request, logBatch, "模拟session", "通过pc端进行登录,开始模拟session" + "账号为:" + account, EnumMonitorLog.LOGSYSTEM_LOGIN.getKey());
        String apiToken = UUIDUtil.getRandomUUID();
        List<String> dptIds = null;
        // 用户权限为仓管时查询该用户的仓库
        if (StringUtils.equals(acntUserBasic.getUserRole(), USER_ROLE_B)) {
            List<AcntDepotRel> acntDepotRels = loginService.findAcntDepotRelsByFirmId(acntUserBasic.getFirmId());
            if (acntDepotRels != null && acntDepotRels.size() > 0) {
                dptIds = new ArrayList<String>();
                for (AcntDepotRel acntDepotRel : acntDepotRels) {
                    dptIds.add(acntDepotRel.getDptId());
                }
            }
        }
        String isCert = acntUserBasic.getIsCert();
        if (StringUtils.equals(isCert, YesOrNoEnum.NO.getKey())) {
            AcntUserCert acntUserCert = new AcntUserCert();
            acntUserCert.setUserId(acntUserBasic.getUserId());
            if (loginService.countAcntUserCert(acntUserCert) == 0) {
                isCert = CertStatusEnum.CERTSTATUS_S.getKey();// 没有认证
                if (loginService.countAcntUserCertFail(acntUserCert) > 0) {
                    isCert = CertStatusEnum.CERTSTATUS_X.getKey();// 认证不通过
                }
            } else {
                acntUserCert = loginService.getOneAcntUserCert(acntUserCert);
                isCert = acntUserCert.getCertStatus();
            }
        }
        AcntUserMall acntUserMall = loginService.selectAcntUserMallByFirmId(acntUserBasic.getFirmId());
        String company = "";
        if (acntUserMall != null) {
            company = acntUserMall.getCompany();
        }

        // 模拟session登录成功
        setSimulateSession( request,
                            acntUserBasic.getUserId(),
                            acntUserBasic.getMobile(),
                            acntUserBasic.getFirmId(),
                            acntUserBasic.getUserType(),
                            acntUserBasic.getUserRole(),
                            company,
                            isCert,
                            dptIds,
                            loginService.selectPrivCodeByFirmId(acntUserBasic.getFirmId()),
                            apiToken,
                            token);
        // 设置cookie
        CookieUtils.setCookie(request, response, CookieConstant.PUT_USERID_NAME, EncryptUtils.encrypt(acntUserBasic.getUserId()), 0);
        // 设置登录token
        CookieUtils.setCookie(request, response, CookieConstant.PUT_TOKEN_INFO, token, 0);
        loginService.insertAcntUserLogin(IpUtil.getIpAddr(request), acntUserBasic.getUserId(), acntUserBasic.getUserRole());
        // 插入uvId userId关系
        RequestUvUserRel requestUvUserRel = new RequestUvUserRel();
        requestUvUserRel.setUserId(acntUserBasic.getUserId());
        requestUvUserRel.setUvId(CookieUtils.getCookieValue(request, CookieConstant.UV_ID));
        requestUvUserRel.setCreateTime(MongoDateUtil.getMongoDate(new Date()));
        loginService.insertRequestUvUserRel(requestUvUserRel);
        super.logInfo(request, logBatch, "模拟session", "通过pc端进行登录,模拟session成功" + "账号为:" + account, EnumMonitorLog.LOGSYSTEM_LOGIN.getKey());
    }


protected void setSimulateSession(  HttpServletRequest request,
                                        String userId,
                                        String mobile,
                                        String firmId,
                                        String userType,
                                        String userRole,
                                        String company,
                                        String isCert,
                                        List<String> dptIds,
                                        List<String> privCodes,
                                        String apiToken,
                                        String token) {
        SessionInfo sessionInfo = new SessionInfo();
        sessionInfo.setMobile(mobile);
        sessionInfo.setFirmId(firmId);
        sessionInfo.setUserType(userType);
        sessionInfo.setUserRole(userRole);
        sessionInfo.setCompanyName(company);
        sessionInfo.setLoginIp(IpUtil.getIpAddr(request));
        sessionInfo.setUserId(userId);
        sessionInfo.setIsCert(isCert);
        sessionInfo.setApiToken(apiToken);
        sessionInfo.setDptIds(dptIds);
        sessionInfo.setPrivCodes(privCodes);
        sessionInfo.setToken(token);
        // 存放登录信息
        redisService.setOjb(SessionConstant.SIMULATE_SESSION_NAME + userId, sessionInfo, 1800);
        // 设置apiToken时间为8小时
        redisService.set(apiToken, "", 8 * 3600);// 默认8个小时
    }

页面拦截器:

<mvc:interceptors>
        <!-- 登录认证 -->
        <mvc:interceptor>
            <mvc:mapping path="/rollGangPay/**" />
            <mvc:mapping path="/rollImport/**" />
            <mvc:mapping path="/rollManage/**" />
            <mvc:mapping path="/rollPublish/**" />
            <mvc:mapping path="/flatImport/**" />
            <mvc:mapping path="/flatManage/**" />
            <mvc:mapping path="/flatPriceModal/**" />
            <!-- 需排除拦截的地址 -->
            <mvc:exclude-mapping path="/rollImport/uploadWare" />
            <mvc:exclude-mapping path="/rollImport/importBendingWare" />
            <mvc:exclude-mapping path="/flatImport/uploadWare" />
            <mvc:exclude-mapping path="/flatImport/importBendingWare" />
            <mvc:exclude-mapping path="/flatImport/stayPublishWare" />
            <bean class="com.maigangle.b2b.common.web.interceptor.AuthLoginInterceptor"></bean>
        </mvc:interceptor>

    </mvc:interceptors>

拦截器类:AuthLoginInterceptor.java

package com.maigangle.b2b.common.web.interceptor;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;

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

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.maigangle.b2b.common.base.SessionInfo;
import com.maigangle.b2b.common.enums.CertStatusEnum;
import com.maigangle.b2b.common.enums.UserRoleEnum;
import com.maigangle.b2b.common.enums.YesOrNoEnum;
import com.maigangle.b2b.common.redis.RedisSpringService;
import com.maigangle.b2b.common.util.EncryptUtils;
import com.maigangle.b2b.common.web.constants.AuthUrlConstant;
import com.maigangle.b2b.common.web.constants.CookieConstant;
import com.maigangle.b2b.common.web.constants.SessionConstant;
import com.maigangle.b2b.common.web.util.CookieUtils;

/**
 * 会员已经认证登录拦截(此文件请不要修改,如需修改请找相应的负责人) 后期要进行拆分保持功能解耦度更低
 * 
 * @author 朱晗
 * @since 2016年11月28日 下午12:36:49
 * @version 1.0
 *
 */
@Repository
public class AuthLoginInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    RedisSpringService redisSpringService;

    private static final String HEADER = "x-requested-with";

    private static final String XML_HTTP_REQUEST = "XMLHttpRequest";

    private String isReferer = YesOrNoEnum.NO.getKey();// 是否referer跳转

    private Map<String, String> excludedUrls;// 指定拦击地址到指定路径

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 判断userId是否为空
        String userId = CookieUtils.getCookieValue(request, CookieConstant.PUT_USERID_NAME);
        System.out.println("userId:" + userId);
        if (StringUtils.isBlank(userId)) {
            return judgeAjaxJumpLogin(request, response);
        }
        // 判断userId是为正确的
        userId = EncryptUtils.decrypt(userId);
        System.out.println("userId:" + userId);
        if (StringUtils.isBlank(userId)) {
            return judgeAjaxJumpLogin(request, response);
        }
        // 判断用户是否已登录
        boolean existLogin = redisSpringService.exists(SessionConstant.SIMULATE_SESSION_NAME + userId);
        System.out.println("existLogin:" + existLogin);
        if (!existLogin) {
            return judgeAjaxJumpLogin(request, response);
        }
        // 判断用户是否已认证
        SessionInfo sessionInfo = redisSpringService.getObj(SessionConstant.SIMULATE_SESSION_NAME + userId, SessionInfo.class);

        String isCert = sessionInfo.getIsCert();
        if (!StringUtils.equals(isCert, CertStatusEnum.CERTSTATUS_Y.getKey())) {
            if (StringUtils.equals(isCert, CertStatusEnum.CERTSTATUS_N.getKey())) {
                // 认证中
                return judgeAjaxJumpAuthIn(request, response);
            } else if (StringUtils.equals(isCert, CertStatusEnum.CERTSTATUS_X.getKey())) {
                // 认证不通过
                return judgeAjaxJumpAuthNoPass(request, response);
            } else if (StringUtils.equals(isCert, CertStatusEnum.CERTSTATUS_S.getKey())) {
                // 没有认证
                return judgeAjaxJumpAuthNo(request, response);
            }
        }
        // 判断是否有相应的商城交易权限
        if (!StringUtils.equals(sessionInfo.getUserRole(), UserRoleEnum.DEALER.getKey())) {
            return judgeAjaxJumpRole(request, response);
        }
        // 判断网路环境是否变化
        /*
         * String requestiIp = IpUtil.getIpAddr(request);
         * System.out.println("requestiIp:"+requestiIp); String loginIp =
         * redisSpringService.getObj(SessionConstant.SIMULATE_SESSION_NAME +
         * userId, SessionInfo.class).getLoginIp();
         * System.out.println("loginIp:"+loginIp); if
         * (!requestiIp.equals(loginIp)) { return judgeAjaxJumpLogin(request,
         * response); }
         */
        redisSpringService.expire(SessionConstant.SIMULATE_SESSION_NAME + userId, 1800);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception {}

    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception {}

    private boolean judgeAjaxJumpLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
        if (StringUtils.equals(isReferer, YesOrNoEnum.NO.getKey())) {
            if (request.getHeader(HEADER) != null && request.getHeader(HEADER).equalsIgnoreCase(XML_HTTP_REQUEST)) {
                response.setHeader("sessionstatus", "interceptorErrpr"); // 响应头设置session状态
                response.setHeader("redirectURL", getReferLoginUrl(request));
                return false;
            } else {
                response.sendRedirect(getRequestLoginUrl(request));
                return false;
            }
        } else {
            String b2bLoginUrl = redisSpringService.getHm(AuthUrlConstant.B2B_AUTH_URL).get(AuthUrlConstant.LOGIN_URL);
            String redirectURL = request.getHeader("referer");
            // 获取referer是否为空,空直接跳转到登录界面
            if (StringUtils.isNotBlank(redirectURL)) {
                if (excludedUrls != null && !excludedUrls.isEmpty()) {
                    for (String key : excludedUrls.keySet()) {
                        if (redirectURL.contains(key)) {
                            redirectURL = redirectURL.replace(key, excludedUrls.get(key));
                            break;
                        }
                    }
                }
                String decodeUrl = URLEncoder.encode(redirectURL, "UTF-8");
                String url = b2bLoginUrl + "?redirectURL=" + decodeUrl;
                if (request.getHeader(HEADER) != null && request.getHeader(HEADER).equalsIgnoreCase(XML_HTTP_REQUEST)) {
                    response.setHeader("sessionstatus", "interceptorErrpr"); // 响应头设置session状态
                    response.setHeader("redirectURL", url);
                    return false;
                } else {
                    response.sendRedirect(url);
                    return false;
                }
            } else {
                response.sendRedirect(getRequestLoginUrl(request));
                return false;
            }
        }

    }

    /**
     * 没有认证
     * 
     * @author 王振光
     * @since 2017年6月14日 上午11:07:40
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    private boolean judgeAjaxJumpAuthNo(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String b2bAuthUrl = redisSpringService.getHm(AuthUrlConstant.B2B_AUTH_URL).get(AuthUrlConstant.LOGIN_URL);
        String redirectUrl = b2bAuthUrl + "/userAuth/noAuth";
        if (request.getHeader(HEADER) != null && request.getHeader(HEADER).equalsIgnoreCase(XML_HTTP_REQUEST)) {
            response.setHeader("sessionstatus", "interceptorErrpr"); // 响应头设置session状态
            response.setHeader("redirectURL", redirectUrl);
            return false;
        } else {
            response.sendRedirect(redirectUrl);
            return false;
        }
    }

    /**
     * 认证中
     * 
     * @author 王振光
     * @since 2017年6月14日 上午11:07:19
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    private boolean judgeAjaxJumpAuthIn(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String b2bAuthUrl = redisSpringService.getHm(AuthUrlConstant.B2B_AUTH_URL).get(AuthUrlConstant.LOGIN_URL);
        String redirectUrl = b2bAuthUrl + "/userAuth/inAuth";
        if (request.getHeader(HEADER) != null && request.getHeader(HEADER).equalsIgnoreCase(XML_HTTP_REQUEST)) {
            response.setHeader("sessionstatus", "interceptorErrpr"); // 响应头设置session状态
            response.setHeader("redirectURL", redirectUrl);
            return false;
        } else {
            response.sendRedirect(redirectUrl);
            return false;
        }
    }

    /**
     * 认证不通过
     * 
     * @author 王振光
     * @since 2017年6月14日 上午11:07:49
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    private boolean judgeAjaxJumpAuthNoPass(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String b2bAuthUrl = redisSpringService.getHm(AuthUrlConstant.B2B_AUTH_URL).get(AuthUrlConstant.LOGIN_URL);
        String redirectUrl = b2bAuthUrl + "/userAuth/noPassAuth";
        if (request.getHeader(HEADER) != null && request.getHeader(HEADER).equalsIgnoreCase(XML_HTTP_REQUEST)) {
            response.setHeader("sessionstatus", "interceptorErrpr"); // 响应头设置session状态
            response.setHeader("redirectURL", redirectUrl);
            return false;
        } else {
            response.sendRedirect(redirectUrl);
            return false;
        }
    }

    /**
     * 角色错误提示<br>
     * 
     * @author 王振光
     * @since 2017年8月8日 上午9:51:31
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    private boolean judgeAjaxJumpRole(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String b2bAuthUrl = redisSpringService.getHm(AuthUrlConstant.B2B_AUTH_URL).get(AuthUrlConstant.LOGIN_URL);
        String redirectUrl = b2bAuthUrl + "/system/roleErr";
        if (request.getHeader(HEADER) != null && request.getHeader(HEADER).equalsIgnoreCase(XML_HTTP_REQUEST)) {
            response.setHeader("sessionstatus", "interceptorErrpr"); // 响应头设置session状态
            response.setHeader("redirectURL", redirectUrl);
            return false;
        } else {
            response.sendRedirect(redirectUrl);
            return false;
        }
    }

    private String getRequestLoginUrl(HttpServletRequest request) throws UnsupportedEncodingException {
        String b2bLoginUrl = redisSpringService.getHm(AuthUrlConstant.B2B_AUTH_URL).get(AuthUrlConstant.LOGIN_URL);
        String redirectURL = request.getRequestURL().toString();
        String query = request.getQueryString();
        if (StringUtils.isNotBlank(query)) {
            redirectURL = redirectURL + "?" + query;
        }
        String decodeUrl = URLEncoder.encode(redirectURL, "UTF-8");
        return b2bLoginUrl + "?redirectURL=" + decodeUrl;
    }

    private String getReferLoginUrl(HttpServletRequest request) throws UnsupportedEncodingException {
        String b2bLoginUrl = redisSpringService.getHm(AuthUrlConstant.B2B_AUTH_URL).get(AuthUrlConstant.LOGIN_URL);
        String redirectURL = request.getHeader("referer");
        String decodeUrl = URLEncoder.encode(redirectURL, "UTF-8");
        return b2bLoginUrl + "?redirectURL=" + decodeUrl;
    }

    public String getIsReferer() {
        return isReferer;
    }

    public void setIsReferer(String isReferer) {
        this.isReferer = isReferer;
    }

    public Map<String, String> getExcludedUrls() {
        return excludedUrls;
    }

    public void setExcludedUrls(Map<String, String> excludedUrls) {
        this.excludedUrls = excludedUrls;
    }

}
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。