session共享

⼀、session共享的⽬的

session共享是为了解决负载均衡的时候session信息不能共享的问题; 即session不能跨服务器访问; session共享可以通过以下五种⽅式实现: 1. 服务器⽂件同步(造成⽂件重复,资源浪费;不建议) 2. session存数据库(加⼤数据库压⼒;不建议) 3. 存放在cookie中(cookie不太安全, 不建议) 4. ip_hash(如果是局域⽹的话会造成这个局域的所有⽤户ip_hash值都⼀样; 不建议) 5. 存缓存(redis, 或者memcache; 推荐使⽤)

⼆、 session共享的实现

以采⽤redis实现为例: 将session存储在redis中, 将cookie作⽤域设置在顶级域名上, 这样SessionID就可以在各个⼦系统之间共享; session共享实现逻辑如下: Controller层, ⽤户登⼊后将token存⼊到cookie中 /** * Controller层逻辑 */ @Controller public class UserController { @Autowired private UserService userService; @Value("${TOKEN_KEY}") private String TOKEN_KEY; // 记录SessionID的cookie名字 @RequestMapping(value="/user/login", method=RequestMethod.POST) @ResponseBody public ResponseResult login(String username, String password, HttpServletResponse response, HttpServletRequest request) { // 检验⽤户是否已经登⼊,若登⼊则返回400错误 String token = CookieUtils.getCookieValue(request, TOKEN_KEY); // 通过token从redis中获取⽤户session ResponseResult userByToken = userService.getUserByToken(token); TbUser data = (TbUser)userByToken.getData(); if(data != null && data.getUsername().equals(username)) { return ResponseResult.build(400, "⽤户已登⼊,请勿重复登⼊"); } // 不是重复登⼊,则执⾏login⽅法 ResponseResult result = userService.login(username, password); // 登⼊成功后写⼊cookie if(result.getStatus() == 200) { // 把token写⼊cookie CookieUtils.setCookie(request, response, TOKEN_KEY, result.getData().toString()); } return result; } } Service层, ⽤户登⼊, 调⽤login, 为⽤户⽣成token, 并以USER_SESSION:token为键, user对象的json串为值,存⼊到redis中; /** * Service层逻辑 */ @Service public class UserServiceImpl implements UserService{ @Autowired private TbUserMapper userMapper; @Autowired private JedisClient jedisClient ; @Value("${USER_SESSION}") private String USER_SESSION; @Value("${SESSION_EXPIRE}") private Integer SESSION_EXPIRE; @Override public ResponseResult getUserByToken(String token) { String json = jedisClient.get(USER_SESSION + ":" + token); if(StringUtils.isBlank(json)) { return ResponseResult.build(400, "⽤户登⼊已过期,请重新登⼊"); } // 重置Session过期时间 jedisClient.expire(USER_SESSION + ":" + token, SESSION_EXPIRE); // 把json转成user对象 TbUser user = JsonUtils.jsonToPojo(json, TbUser.class); return ResponseResult.ok(user); } @Override public ResponseResult login(String userName, String password) { // 判断⽤户名和密码是否正确 TbUser user = new TbUser(); user.setUsername(userName); List list = userMapper.selectByRecord(user); if(list == null || list.size() == 0) { return ResponseResult.build(400, "⽤户名或密码不正确"); } TbUser resultUser = list.get(0); // 校验密码是否正确 if(!DigestUtils.md5DigestAsHex(password.getBytes()) .equals(resultUser.getPassword())) { return ResponseResult.build(400, "⽤户名或密码不正确"); } // 使⽤UUID⽣成token String token = UUID.randomUUID().toString(); // 清空密码 resultUser.setPassword(null); // 把⽤户信息保存到redis,key为token,value为⽤户信息。 jedisClient.set(USER_SESSION + ":" + token, JsonUtils.objectToJson(resultUser)); // 设置token过期时间 jedisClient.expire(USER_SESSION + ":" + token, SESSION_EXPIRE); // 返回登⼊成功, 返回token return ResponseResult.ok(token); } } CookieUtil, 设置cookie作⽤域顶级域名, 解决cookie跨域让⼦系统共享 public final class CookieUtils { /** * 设置Cookie的值 不设置⽣效时间默认浏览器关闭即失效,也不编码 */ public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue) { doSetCookie(request, response, cookieName, cookieValue, -1, true); } /** * 设置Cookie的值,并使其在指定时间内⽣效 * @param cookieMaxage cookie⽣效的最⼤秒数 */ private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) { try { if (cookieValue == null) { cookieValue = ""; } else if (isEncode) { cookieValue = URLEncoder.encode(cookieValue, "utf-8"); } Cookie cookie = new Cookie(cookieName, cookieValue); if (cookieMaxage > 0) cookie.setMaxAge(cookieMaxage); if (null != request) {// 设置域名的cookie String domainName = getDomainName(request); System.out.println(domainName); if (!"localhost".equals(domainName)) { cookie.setDomain(domainName); } } cookie.setPath("/"); response.addCookie(cookie); } catch (Exception e) { e.printStackTrace(); } } /** * 得到cookie的顶级域名 */ public static final String getDomainName(HttpServletRequest request) { String domainName = null; String serverName = request.getRequestURL().toString(); if (serverName == null || serverName.equals("")) { domainName = ""; } else { serverName = serverName.toLowerCase(); serverName = serverName.substring(7); final int end = serverName.indexOf("/"); serverName = serverName.substring(0, end); final String[] domains = serverName.split("\\."); int len = domains.length; if (len > 3) { // www.xxx.com.cn domainName = "." + domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1]; } else if (len 1) { // xxx.com or xxx.cn domainName = "." + domains[len - 2] + "." + domains[len - 1]; } else { domainName = serverName; } } if (domainName != null && domainName.indexOf(":") > 0) { String[] ary = domainName.split("\\:"); domainName = ary[0]; } return domainName;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值