`
tangkuo
  • 浏览: 94734 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

session共享多节点部署之redis

阅读更多
第一步:导入相关依赖jar包在pom.xml文件;
<!-- redis依赖 start -->
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- spring session的依赖 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
        <dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
<!-- redis依赖 end -->

第二步:配置文件配置连接redis相关配置项;
#redis的ip地址 
spring.redis.host=10.4.4.11
#密码 
spring.redis.password=sdj
#端口号 
spring.redis.port=6379
#spring.redis.database=0
#spring.session.store-type=redis

#开启cookie安全
server.servlet.session.cookie.secure=false


#客户端超时时间单位是毫秒 默认是2000
redis.timeout=100000 

#最大空闲数 
redis.maxIdle=5
#最小空闲数
redis.minIdle=2 
#连接池的最大数据库连接数。设为0表示无限制,如果是jedis 2.4以后用redis.maxTotal 
redis.maxTotal=20
#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。 
redis.maxWaitMillis=1000
#是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个 
redis.testOnBorrow=true 

第三步:编写连接redis工具类 RedisConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.pay.common.util.RedisUtil;
import com.pay.common.util.UtilJedis;

import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
* redis配置类
*
* @author
*
*/
@Configuration
public class RedisConfig {

@Value("${redis.maxIdle}")
private Integer maxIdle;

@Value("${redis.minIdle}")
private Integer minIdle;

@Value("${redis.maxTotal}")
private Integer maxTotal;

@Value("${redis.maxWaitMillis}")
private Integer maxWaitMillis;

@Value("${redis.testOnBorrow}")
private boolean testOnBorrow;

@Value("${spring.redis.host}")
private String hostName;

@Value("${spring.redis.port}")
private Integer port;

@Value("${spring.redis.password}")
private String password;

@Value("${redis.timeout}")
private Integer timeout;

/**
* JedisPoolConfig 连接池
*
* @return
*/
@Bean
public JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// 最大空闲数
jedisPoolConfig.setMaxIdle(maxIdle);
// 连接池的最大数据库连接数
jedisPoolConfig.setMaxTotal(maxTotal);
jedisPoolConfig.setMinIdle(minIdle);
// 最大建立连接等待时间
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
jedisPoolConfig.setTestOnBorrow(testOnBorrow);

return jedisPoolConfig;
}

@Bean
public JedisPool redisPoolFactory() {
JedisPool jedisPool = new JedisPool(jedisPoolConfig(), hostName, port, timeout, password, 0, "partner:1");
return jedisPool;
}

@Bean(name = "redisUtil")
public RedisUtil redisUtil() {
RedisUtil redisUtil = new RedisUtil();
redisUtil.setJedisPool(redisPoolFactory());
redisUtil.setUtilJedis(getUtilJedis());
return redisUtil;
}

@Bean(name = "utilJedis")
public UtilJedis getUtilJedis() {
return new UtilJedis();
}
}

获取图形验证码接口需要将sessionId对应的图形验证码值存入redis;
String jsessionid = session.getId();
  // 验证码保存到redis;
  redisUtil.setValAndExpire(Constants.REDIS_INVESTOR_CODE_PREFIX + jsessionid, Constants.CODE_TIMEOUT, verifyCode);


第四步: 拦截器处理 LoginInterceptor;
public class LoginInterceptor extends HandlerInterceptorAdapter {

@Autowired
private RedisUtil redisUtil;

//public static String timeOutTemp;
/**
* session超时时间
*/
@Value("${cookie.timeout}")
protected String timeout;
@Autowired
private Environment env;


HttpSession session = request.getSession();
Object username = session.getAttribute(Constants.LOGIN_USER_NAME);
// 分布式环境部署sessionId读取redis存储登录对象信息;
String jsessionid = request.getSession().getId();
// 读取缓存redis登陆态信息
String loginUserInfo = (String) redisUtil.getObject(Constants.SESSION_AUTH + jsessionid);
LoginUserInfo lu = null;
if (StringUtils.isNotBlank(loginUserInfo) && null != JSONValidator.from(loginUserInfo)
&& JSONValidator.from(loginUserInfo).validate()) {
lu = JSON.parseObject(loginUserInfo, LoginUserInfo.class);
}



/**
* 判断同一个登录账号是否在多个浏览器客户端登录成功;
*
* @Title: checkSessionId
* @Description: (校验sessionId是否过期失效)
* @param loginId   String
* @param sessionId String
* @return boolean 返回类型
*/
private boolean checkSessionId(String loginId, String sessionId, HttpServletRequest request) {
boolean flag = true;
// 根据登录查询用户信息,判断userName与sessionId存储在redis中的登录账号名称是否一致;
String jsessionid = request.getSession().getId();
String loginUserInfo = (String) redisUtil.getObject(Constants.SESSION_AUTH + jsessionid);
LoginUserInfo auth = JSON.parseObject(loginUserInfo, LoginUserInfo.class);
if(null == auth) {
return false;
}
//登录账号多端登录,自动踢出系统;
String userName = auth.getLoginName();
String storeRedisJsessionid = redisUtil.getKeyValue(Constants.REDIS_LOGIN_PREFIX + userName);

//     LogUtil.MSG.info("checkSessionId is start 请求报文:sessionId=" + sessionId+"userName="+LogUtil.getName(loginId));
//   LogUtil.MSG.info("checkSessionId is end 响应报文:" + LogUtil.printReqMsg(userInfo));
if (null != auth && jsessionid.equals(storeRedisJsessionid)) {
// 同一客户端登录(当前登录账号对应的sessionId值与数据库存储的Jsessionid一致)
} else {
// 更新数据库sessionId
flag = false;
}
return flag;
}

第五步: 登录接口处理LoginController;
@RequestMapping(value = "/login.action", method = RequestMethod.POST)
@ResponseBody
public String login(HttpServletRequest request, String randomCode) {
LogUtil.MSG.info("【用户输入验证码】 randomCode:【{}】", randomCode);
Map<String, String> map = new HashMap<String, String>();
try {
String sessionId = request.getSession().getId();
LogUtil.MSG.debug("sessionId:{}", sessionId);
//String verifyCode = (String) request.getSession().getAttribute(Constants.SESSION_RANDOMCODE);
String verifyCode = redisUtil.getKeyValue(Constants.REDIS_INVESTOR_CODE_PREFIX + sessionId);
Boolean isResponseCorrect = checkVerifyCode(randomCode, verifyCode);
if (isResponseCorrect) {
request.getSession().removeAttribute(Constants.SESSION_RANDOMCODE);


request.getSession().setAttribute(Constants.LOGIN_USER_INFO, lu);
request.getSession().setAttribute(Constants.LOGIN_USER_NAME, userName);
request.getSession().setAttribute(Constants.OPERATE_DATE, String.valueOf(new Date().getTime()));
        request.getSession().setAttribute(Constants.LOGIN_USER_ID, String.valueOf(lu.getOperatorId()));

//登录成功将用户对象存入redis;
//String redisKey = userName;
String jsessionid = sessionId;
redisUtil.setValAndExpire(Constants.REDIS_LOGIN_PREFIX + userName, Constants.REDIS_TIMEOUT, jsessionid);
// 登录信息放入redis
redisUtil.setExObject(Constants.SESSION_AUTH + jsessionid, Constants.REDIS_TIMEOUT, JSONObject.toJSONString(lu));




第六步退出登录接口处理 logout;
@RequestMapping(value = "/logout.action")
public String logout(HttpServletRequest request) {
HttpSession session = request.getSession();
//退出登录从redis中删除;
String jsessionid = session.getId();
// 读取缓存redis登陆态信息
redisUtil.del(Constants.SESSION_AUTH + jsessionid);
String userName = (String) session.getAttribute("userName");
if (userName != null) {
session.removeAttribute("userName");
}
String redirectUrl = "/";
String profile = env.getProperty("spring.cloud.config.profile");
if(!"dev".equals(profile)) {
String contenxtPath = request.getContextPath();
contenxtPath = "/".equals(contenxtPath) || "".equals(contenxtPath) ? contenxtPath + "/" + EnvProperties.getDomain() : contenxtPath;
redirectUrl = contenxtPath;
}
return "redirect:" + redirectUrl;
}


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics