基于Redis+Cookie实现Session共享

分布式项目中要实现单点登录(SSO - Single Sign On):对于同一个客户端(例如 Chrome 浏览器),只要登录了一个子站(例如 a.com),则所有子站(b.comc.com)都认为已经登录。
比如用户在登录淘宝后,跳转到天猫时就已经登录了。

通过redis缓存和cookie实现单点登录:

基于Redis+Cookie实现Session共享_第1张图片

登录接口逻辑处理:


  1. @ResponseBody
  2. @RequestMapping("/dologin")
  3. public Result doLogin(String nickname,String password,HttpServletResponse response){
  4. User loginUser = userDao.selectUserByNickName(nickname);
  5. if(loginUser == null){
  6. return Result.error(CodeMsg.NICKNAME_NOT_EXIST);
  7. }
  8. String salt = loginUser.getSalt();
  9. //将表单提交的密码二次md5
  10. String s = Md5Utils.formPassToDb(password, salt);
  11. //验证密码
  12. if(s.equals(loginUser.getPassword())){
  13. //生成随机的token
  14. String token = UUIDUtil.uuid();
  15. //将token和用户作为key与value存入缓存
  16. redisService.set(MiaoSha_UserKey.userKeyToken,token,loginUser);
  17. //封装cookie
  18. Cookie cookie = new Cookie(COOKIE_NAME,token);
  19. //设置cookie过期时间
  20. cookie.setMaxAge(MiaoSha_UserKey.userKeyToken.getExpireSeconds());
  21. cookie.setPath("/");
  22. response.addCookie(cookie);
  23. return Result.success(token);
  24. }
  25. return Result.error(CodeMsg.SERVER_ERROR);
  26. }

在其他接口中获取到登录用户,自定义一个参数解析器HandlerMethodArgumentResolver
在进行参数判断中可自定义一个注解,当某个参数被使用该注解后,则调用自定义的参数管理器


  1. @Target(value = ElementType.PARAMETER)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. public @interface UserParameter {
  5. }

HandlerMethodArgumentResolver :


  1. @Component
  2. public class UserArgumentResolver implements HandlerMethodArgumentResolver {
  3. @Autowired
  4. private UserService userService;
  5. //先判断参数类型和是否贴了自定义注解,满足则进行下一步
  6. @Override
  7. public boolean supportsParameter(MethodParameter parameter) {
  8. return parameter.getParameterType() == User.class && parameter.hasParameterAnnotation(UserParameter.class);
  9. }
  10. @Override
  11. public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory){
  12. HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
  13. Cookie[] cookies = request.getCookies();
  14. if(cookies == null || cookies.length <=0){
  15. return null;
  16. }
  17. String token = null;
  18. for(Cookie cookie : cookies){
  19. if(cookie.getName().equals(LoginController.COOKIE_NAME)){
  20. //拿到token
  21. token = cookie.getValue();
  22. break;
  23. }
  24. }
  25. User user = userService.getUserByToken(token);
  26. return user;
  27. }
  28. }

遍历所有的cookie,直到找到登录时设置的 public static final String COOKIE_NAME = "token"; 获取该cookie的值(token)并查找redis拿到用户

将自定义解析器配置到springmvc管理:


  1. @Configuration
  2. public class WebMvcConfig implements WebMvcConfigurer {
  3. @Autowired
  4. private UserArgumentResolver userArgumentResolver;
  5. @Override
  6. public void addArgumentResolvers(List resolvers) {
  7. resolvers.add(userArgumentResolver);
  8. }
  9. }

你可能感兴趣的:(redis,数据库,缓存)