环境需求:redis3.8.2+maven+springBoot+jdk1.8+freemarker模板
1、需求背景
周末在家,上家同事突然联系,让我给他网站做单点登入功能,于是自己先梳理逻辑,实现功能并且记录下来。
单点登入(Single sign on)顾名思义,就是在一个网站登入之后,其他网站就不需要用户继续输入账号密码,而能免密登入,这种技术在大型网站都使用的非常频繁,比如阿里巴巴,当用户登入他们系统后,每个子系统都能自动登入,如果大家在登入某宝之后,登入某碑,也需要密码,登入淘宝也需要重新输入密码,这肯定会造成用户体验极差,而且系统的认证逻辑也会很麻烦,这时候单点登入就出现了。
2、代码实例
本文演示两个系统
@Slf4j @RestController @RequestMapping("/redis/single") public class RedisSingleController { private static final String NAME = "name"; private static final String PASSWORD = "password"; @Resource private RedisTemplate redisTemplate; @GetMapping("/login_page") public ModelAndView loginPage(){ ModelAndView mv = new ModelAndView(); mv.setViewName("loginPage"); return mv; } /** * 系统1 * @return */ @GetMapping("/system1") public ModelAndView system1(HttpServletRequest request){ ModelAndView mv = new ModelAndView(); if(redisTemplate.hasKey("name")){ mv.setViewName("systemOnePage"); return mv; } request.getSession().setAttribute("goUrl","indexSystem1"); mv.setViewName("loginPage"); return mv; } /** * 系统2 * @return */ @GetMapping("/system2") public ModelAndView system2(HttpServletRequest request){ ModelAndView mv = new ModelAndView(); if(redisTemplate.hasKey("name")){ mv.setViewName("systemTwoPage"); return mv; } request.getSession().setAttribute("goUrl","indexSystem2"); mv.setViewName("loginPage"); return mv; } /** * 效验账号密码是否正常 * @param name * @param password * @return */ @PostMapping("/detection") @ResponseBody public Map<String, Object> index( String name, String password, String gotoUrl){ Map<String, Object> map = new HashMap<>(); if(!ObjectUtil.equals(name,NAME) || !ObjectUtil.equals(password,PASSWORD)){ map.put("flag",false); map.put("data","账号密码不匹配!"); return map; } map.put("flag",true); map.put("data","账号密码正确!"); //redis缓存20s失效 redisTemplate.opsForValue().set("name",name,10, TimeUnit.SECONDS); return map; } /** * 登入成功,系统一进入首页 * @return */ @GetMapping("/indexSystem1") @ResponseBody public ModelAndView index(){ ModelAndView mv = new ModelAndView(); mv.setViewName("systemOnePage"); return mv; } /** * 登入成功,系统二进入首页 * @return */ @GetMapping("/indexSystem2") @ResponseBody public ModelAndView indexSystem2(){ ModelAndView mv = new ModelAndView(); mv.setViewName("systemTwoPage"); return mv; }
1、保证访问系统一登入页面时,进入的是系统一首页,访问系统二登入页面时,进入的是系统二首页。
2、在访问系统一或者系统二时,都需要判断redis里是否存在当前用户,存在则免密登入。
3、逻辑处理,在登入先判断数据库里的账号密码是否正确,若用户在页面登入正确,则返回登入成功,并且存入redis,给他设置过期时间。
4、保证在redis过期时间内其他子系统都能免密登入。