springcloud微服务基于redis集群的单点登录实现解析
发布时间:2020-12-14 19:40:40 所属栏目:Java 来源:网络整理
导读:简介 本文介绍微服务架构中如何实现单点登录功能 创建三个服务: 操作redis集群的服务,用于多个服务之间共享数据 统一认证中心服务,用于整个系统的统一登录认证 服务消费者,用于测试单点登录 大体思路:每个服务都设置一个拦截器检查cookie中是否有token,
简介 本文介绍微服务架构中如何实现单点登录功能 创建三个服务:
大体思路:每个服务都设置一个拦截器检查cookie中是否有token,若有token,则放行,若没有token,重定向到统一认证中心服务进行登录,登录成功后返回到被拦截的服务。 搭建redis集群服务 搭建redis集群参考文档 搭建统一认证中心 主函数添加注解 /** * 单点登录既要注册到服务注册中心,又要向redis服务系统获取鼓舞 * 所以要添加 @EnableDiscoveryClient @EnableEurekaClient 两个注解 * */ @EnableDiscoveryClient @EnableEurekaClient @EnableFeignClients @MapperScan(basePackages = "com.example.itokenservicesso.mapper") @SpringBootApplication public class ItokenServiceSsoApplication { public static void main(String[] args) { SpringApplication.run(ItokenServiceSsoApplication.class,args); } } 消费redis服务和熔断器 @FeignClient(value = "itoken-service-redis",fallback = RedisServiceFallBack.class) public interface RedisService { @PostMapping(value = "put") public String put(@RequestParam(value = "key") String key,@RequestParam(value = "value") String value,@RequestParam(value = "seconds") long seconds); @GetMapping(value = "get") public String get(@RequestParam(value = "key") String key); } @Component public class RedisServiceFallBack implements RedisService { @Override public String put(String key,String value,long seconds) { return FallBack.badGateWay(); } @Override public String get(String key) { return FallBack.badGateWay(); } } public class FallBack { public static String badGateWay(){ try { return JsonUtil.objectToString(ResultUtil.error(502,"内部错误")); } catch (JsonProcessingException e) { e.printStackTrace(); } return null; } } 登录服务 @Service public class LoginServiceImpl implements LoginService { @Autowired private UserMapper userMapper; @Autowired private RedisService redisService; @Override public User login(String loginCode,String plantPassword) { //从缓存中获取登录用户的数据 String json = redisService.get(loginCode); User user = null; //如果缓存中没有数据,从数据库取数据 if (json == null) { user = userMapper.selectAll(loginCode); String passwordMd5 = DigestUtils.md5DigestAsHex(plantPassword.getBytes()); if (user != null && passwordMd5.equals(user.getPassword())) { //登录成功,刷新缓存 try { redisService.put(loginCode,JsonUtil.objectToString(user),60 * 60 * 24); } catch (JsonProcessingException e) { e.printStackTrace(); } return user; } else { return null; } } //如果缓存中有数据 else { try { user = JsonUtil.stringToObject(json,User.class); } catch (IOException e) { e.printStackTrace(); } } return user; } } contoller层,处理登录业务和登录跳转 登录业务 /** * 登录业务 * * @param loginCode * @param password * @return */ @PostMapping("login") public String login(String loginCode,String password,@RequestParam(required = false) String url,HttpServletRequest request,HttpServletResponse response,RedirectAttributes redirectAttributes) { User user = loginService.login(loginCode,password); //登录成功 if (user != null) { String token = UUID.randomUUID().toString(); //将token放入缓存 String result = redisService.put(token,loginCode,60 * 60 * 24); //如果redisService没有熔断,也就是返回ok,才能执行 if (result != null && result.equals("ok")) { CookieUtil.setCookie(response,"token",token,60 * 60 * 24); if (url != null && !url.trim().equals("")) return "redirect:" + url; } //熔断后返回错误提示 else { redirectAttributes.addFlashAttribute("message","服务器异常"); } } //登录失败 else { redirectAttributes.addFlashAttribute("message","用户名或密码错误"); } return "redirect:/login"; } 登录跳转 @Autowired private LoginService loginService; @Autowired private RedisService redisService; /** * 跳转登录页 */ @GetMapping("login") public String login(HttpServletRequest request,Model model,@RequestParam(required = false) String url ) { String token = CookieUtil.getCookie(request,"token"); //token不为空可能已登录,从redis获取账号 if (token != null && token.trim().length() != 0) { String loginCode = redisService.get(token); //如果账号不为空,从redis获取该账号的个人信息 if (loginCode != null && loginCode.trim().length() != 0) { String json = redisService.get(loginCode); if (json != null && json.trim().length() != 0) { try { User user = JsonUtil.stringToObject(json,User.class); //已登录 if (user != null) { if (url != null && url.trim().length() != 0) { return "redirect:" + url; } } //将登录信息传到登录页 model.addAttribute("user",user); } catch (IOException e) { e.printStackTrace(); } } } } return "login"; } 搭建服务消费者:添加一个拦截器,判断token是否为空 拦截器 public class WebAdminInterceptor implements HandlerInterceptor { @Autowired private RedisService redisService; @Override public boolean preHandle(HttpServletRequest request,Object handler) throws Exception { String token = CookieUtil.getCookie(request,"token"); //token为空,一定没有登录 if (token == null || token.isEmpty()) { response.sendRedirect("http://localhost:8503/login?url=http://localhost:8601/login"); return false; } return true; } @Override public void postHandle(HttpServletRequest request,Object handler,ModelAndView modelAndView) throws Exception { HttpSession session = request.getSession(); User user = (User) session.getAttribute("user"); //已登陆状态 if (user != null) { if (modelAndView != null) { modelAndView.addObject("user",user); } } //未登录状态 else { String token = CookieUtil.getCookie(request,"token"); if (token != null && !token.isEmpty()) { String loginCode = redisService.get(token); if (loginCode != null && !loginCode.isEmpty()) { String json = redisService.get(loginCode); if (json != null && !json.isEmpty()) { //已登录状态,创建局部会话 user = JsonUtil.stringToObject(json,User.class); if (modelAndView != null) { modelAndView.addObject("user",user); } request.getSession().setAttribute("user",user); } } } } //二次确认是否有用户信息 if (user == null) { response.sendRedirect("http://localhost:8503/login?url=http://localhost:8601/login"); } } @Override public void afterCompletion(HttpServletRequest request,Exception ex) throws Exception { } } 配置拦截器 @Configuration public class WebAdminInterceptorConfig implements WebMvcConfigurer { //将拦截器设置为Bean,在拦截其中才能使用@AutoWired注解自动注入 @Bean WebAdminInterceptor webAdminInterceptor() { return new WebAdminInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(webAdminInterceptor()) .addPathPatterns("/**") .excludePathPatterns("/static"); } } 任意写一个接口,触发拦截器进行测试 @RequestMapping(value = {"/login"}) public String index(){ return "index"; } 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |