redis缓存+session 实现单点登录
Posted 王大军
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis缓存+session 实现单点登录相关的知识,希望对你有一定的参考价值。
一、单点登录介绍
单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
同域下:单点登录是巧用了Cookie顶域的特性。
不同域下:如果是不同域呢?不同域之间Cookie是不共享的,怎么办? 这个是使用CAS流程,单点登录的标准流程。
相关详情:https://yq.aliyun.com/articles/636281
https://blog.csdn.net/qq_34246546/article/details/79493208
二、同域下的单点登录:利用sessionID+cookie+redis
注意:因为我们是通过cookie的顶域特性,所以需要通过域名访问才能生成指定的cookie名称mmall_login_token 的cookie
自定义域名相关集群和负载均衡:https://www.cnblogs.com/FondWang/p/11677319.html
1. cookie工具类
package com.mmall.util; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * cookie工具类 */ @Slf4j public class CookieUtil { private static final String COOKIE_DOMAIN = "wangjun.com"; //顶级域名 private static final String COOKIE_NAME = "mmall_login_token";//cookieName /** * 从请求中读取cookie * @param request * @return */ public static String readLoginToken(HttpServletRequest request){ Cookie[] cks = request.getCookies(); if (cks != null){ for (Cookie cookie : cks){ log.info("read cookieName:{}, cookieValue:{}",cookie.getName(),cookie.getValue()); if (StringUtils.equals(cookie.getName(),COOKIE_NAME)){ log.info("return cookieName:{}, cookieValue:{}",cookie.getName(),cookie.getValue()); return cookie.getValue(); } } } return null; } /** * 写入cookie * @param response * @param token */ public static void writeLoginToken(HttpServletResponse response, String token){ Cookie cookie = new Cookie(COOKIE_NAME, token); cookie.setDomain(COOKIE_DOMAIN); cookie.setPath("/"); //代表根目录,根目录以下的代码和页面可以获取到cookie //单位秒,如果不设置maxage,cookie就不会写入硬盘,而是写入内存,只在当前页面有效 cookie.setMaxAge(60 * 60 * 24 * 365); log.info("write cookieName:{}, cookieValue:{}", cookie.getName(),cookie.getValue()); response.addCookie(cookie); } /** * 删除cookie * @param request * @param response */ public static void delLoginToken(HttpServletRequest request, HttpServletResponse response){ Cookie[] cks = request.getCookies(); if (cks != null){ for (Cookie cookie : cks){ if (StringUtils.equals(cookie.getName(),COOKIE_NAME)){ cookie.setDomain(COOKIE_DOMAIN); cookie.setPath("/"); cookie.setHttpOnly(true); //无法用脚本访问cookie。当然不能全面防止,但可以提高安全性 cookie.setMaxAge(0);//设置为0,代表删除此cookie log.info("del cookieName:{}, cookieValue:{}", cookie.getName(),cookie.getValue()); response.addCookie(cookie); return; } } } } }
2. redis相关内容
(1)使用集群:https://www.cnblogs.com/FondWang/p/11690791.html
(2)单机redis:https://www.cnblogs.com/FondWang/p/11681222.html
3. json对象转换
作用:将登录信息转换陈json,存储到redis中。
https://www.cnblogs.com/FondWang/p/11703197.html
4. 登录代码
@Controller
@RequestMapping("/user/")
public class UserController {
@Autowired
private IUserService iUserService;
/**
* 用户登录
* @param username
* @param password
* @param session
* @return
*/
@RequestMapping(value = "login.do",method = RequestMethod.POST)
@ResponseBody
public ServiceResponse<User> login(String username, String password, HttpSession session, HttpServletResponse httpServletResponse){
ServiceResponse<User> response = iUserService.login(username, password);
if (response.isSuccess()){
CookieUtil.writeLoginToken(httpServletResponse,session.getId()); //将内容写入cookie中
RedisShardedPoolUtil.setEx(session.getId(), JsonUtil.obj2String(response.getData()), Const.RedisCacheExtime.REDIS_SESSION_EXTIME);
}
return response;
}
/**
* 登出 删除session
* @param httpServletRequest
* @return
*/
@RequestMapping(value = "logout.do",method = RequestMethod.POST)
@ResponseBody
public ServiceResponse<String> logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
String loginToken = CookieUtil.readLoginToken(httpServletRequest); //获取cookie的sessionID,如果存在,删除登出
CookieUtil.delLoginToken(httpServletRequest,httpServletResponse); //删除cookie中对应的token用户信息
RedisShardedPoolUtil.del(loginToken); //删除对应redis的用户信息
return ServiceResponse.createBySuccess("已登出");
}
}
三、不同域下的单点登录
待更新
以上是关于redis缓存+session 实现单点登录的主要内容,如果未能解决你的问题,请参考以下文章
spring-session实现session共享案例(单点登录)
原保存一下之前spring-session的redis单点登录配置文件跨域