分布式环境下用redis模拟session
首先为什么使用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;
}
}
- 上一篇: .Net 4.5中的HttpClient使用方法
- 下一篇: .net中http接口相关