一、前言

小编在前一篇博客中向大家介绍了使用单点登录的演变过程,最后一步的时候小编向大家展示了分布式架构。其中就用到了单点登录系统。这篇博客继续接上一篇博客,实现一下单点登录系统。

二、环境准备

  • Eclipse

  • Redis

三、单点登录流程图

这个是简单的单点登录流程图,就那淘宝来说,当我们进步淘宝首页的时候是没有登录的,点击登录的时候,会跳转到用户登录界面。此时的用户登录界面就是咱们SSO系统的一部分,根据登录的要求,会接收用户名和密码,然后根据用户名查询密码是否正确。
如果不正确就跳转到登录页,提示不正确;
如果正确就要进行以下步骤:
1. 生成一个uuid,作为token;
2. 把用户信息序列化存储到redis,存储的key为token,存储成功后,返回token;
3. 把token存储到cookie;
4. 判断是否有回调url,如果有,跳转到指定url;如果没有,跳转到系统首页;

四、实现过程

4.1 使用到的技术

  • Mybatis

  • Spring

  • Springmvc

  • Jedis

4.2 创建项目

创建Maven项目:

4.3 依赖的jar包

pom文件:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.dmsd</groupId><artifactId>parent</artifactId><version>0.0.1-SNAPSHOT</version></parent><groupId>com.dmsd</groupId><artifactId>sso</artifactId><version>0.0.1-SNAPSHOT</version><packaging>war</packaging><dependencies><dependency><groupId>com.dmsd</groupId><artifactId>dao</artifactId><version>0.0.1-SNAPSHOT</version></dependency><!-- Spring --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><scope>provided</scope></dependency><dependency><groupId>javax.servlet</groupId><artifactId>jsp-api</artifactId><scope>provided</scope></dependency><!-- Redis客户端 --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency></dependencies><!-- 添加tomcat插件 --><build><plugins><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><configuration><port>8084</port><path>/</path></configuration></plugin></plugins></build></project>

4.4 整合SSM框架

这里的整合可以参考小编以前写的SSM整合博客。

4.5 登录逻辑实现

DAO层:

直接使用Mybatis逆向工程产生的代码。

Service层:

接收参数:用户名、密码。

校验密码是否正确,生成token,向redis中写入用户信息,把token写入cookie,返回SystemResult实体包含token。

参数:用户名、密码、HttpServletResponse、HttpServletRequest
返回值:TaotaoResult

@Service
public class LoginServiceImpl implements LoginService {@Autowiredprivate TbUserMapper userMapper;@Autowiredprivate JedisClient jedisClient;@Value("${REDIS_SESSION_KEY}")private String REDIS_SESSION_KEY;@Value("${SESSION_EXPIRE}")private Integer SESSION_EXPIRE;@Overridepublic SystemResult login(String username, String password, HttpServletRequest request,HttpServletResponse response) {//校验用户名密码是否正确TbUserExample example = new TbUserExample();Criteria criteria = example.createCriteria();criteria.andUsernameEqualTo(username);List<TbUser> list = userMapper.selectByExample(example);//取用户信息if (list == null || list.isEmpty()) {return TaotaoResult.build(400, "用户名或密码错误");}TbUser user = list.get(0);//校验密码if(!user.getPassword().equals(DigestUtils.md5DigestAsHex(password.getBytes()))) {return SystemResult.build(400, "用户名或密码错误");}//登录成功//生成tokenString token = UUID.randomUUID().toString();//把用户信息写入redis//key:REDIS_SESSION:{TOKEN}//value:user转jsonuser.setPassword(null);jedisClient.set(REDIS_SESSION_KEY + ":" + token, JsonUtils.objectToJson(user));//设置session的过期时间jedisClient.expire(REDIS_SESSION_KEY + ":" + token, SESSION_EXPIRE);//写cookieCookieUtils.setCookie(request, response, "TT_TOKEN", token);return SystemResult.ok(token);}}

Controller层:

请求的url:/user/login
      接收参数:username、password
      调用Service,返回taotaoResult对象。
      响应json数据。

@Controller
public class LoginController {@Autowiredprivate LoginService loginService;@RequestMapping(value="/user/login", method=RequestMethod.POST)@ResponseBodypublic SystemResult login(String username, String password, HttpServletRequest request, HttpServletResponse response) {try {SystemResult result = loginService.login(username, password, request, response);return result;} catch (Exception e) {e.printStackTrace();return SystemResult.build(500, ExceptionUtil.getStackTrace(e));}}
}

4.6 通过token查询用户信息

说明:根据token到redis查询用户信息,如果用户信息不存在说明session已经过期,返回400并提示用户session已经过期。如果查询到用户,返回用户信息,并且更新一下用户的过期时间。

请求url:/user/token/{token}

需要支持jsonp

返回:SystemResult

Dao层:

使用Jedis访问redis实现。

Service层:

参数:String token
      根据token查询redis,查询到结果返回用户对象,更新过期时间。如果查询不到结果,返回Session已经过期,状态码400.
      返回值:SystemResult

@Overridepublic SystemResult getUserByToken(String token) {// 根据token取用户信息String json = jedisClient.get(REDIS_SESSION_KEY + ":" + token);//判断是否查询到结果if (StringUtils.isBlank(json)) {return SystemResult.build(400, "用户session已经过期");}//把json转换成java对象TbUser user = JsonUtils.jsonToPojo(json, TbUser.class);//更新session的过期时间jedisClient.expire(REDIS_SESSION_KEY + ":" + token, SESSION_EXPIRE);return SystemResult.ok(user);}

Controller:

请求的url:/user/token/{token}
      从url中取token的内容,调用Service取用户信息,返回TaotaoResult。(json数据)

@RequestMapping("/user/token/{token}")@ResponseBodypublic Object getUserByToken(@PathVariable String token, String callback) {try {TaotaoResult result = loginService.getUserByToken(token);//支持jsonp调用if (StringUtils.isNotBlank(callback)) {MappingJacksonValue mappingJacksonValue = new MappingJacksonValue(result);mappingJacksonValue.setJsonpFunction(callback);return mappingJacksonValue;}return result;} catch (Exception e) {e.printStackTrace();return SystemResult.build(500, ExceptionUtil.getStackTrace(e));}}

首页系统中登录跳转的代码:

这里使用Ajax的跨域调用,先获取到存储在浏览器的cookie,然后使用Ajax的Jsonp来跨域调用用户信息,由于返回的是SystemResult的json形式,他包含了err、msg、data三个部分,所以要获取用户信息的时候就要通过data.data.username来获取。

var TT = TAOTAO = {checkLogin : function(){var _ticket = $.cookie("TT_TOKEN");if(!_ticket){return ;}$.ajax({url : "http://localhost:8084/user/token/" + _ticket,dataType : "jsonp",type : "GET",success : function(data){if(data.status == 200){var username = data.data.username;var html = username + ",欢迎来到!<a href=\"http://www.taotao.com/user/logout.html\" class=\"link-logout\">[退出]</a>";$("#loginbar").html(html);}}});}
}$(function(){// 查看是否已经登录,如果已经登录查询登录信息TT.checkLogin();
});

五、小结

这次的单点登录主要是使用redis完成的。redis真是一个非常好用的缓存技术。在很多方面都做了出色的表现。另外,就是这种产生分布式,把登录系统单独提取出来,这种思想有是很棒的。加油!

【SSO】单点登录系统实现相关推荐

  1. SpringBoot+MyBatis+Redis实现SSO单点登录系统(二)

    SpringBoot+MyBatis+Redis实现SSO单点登录系统(二) 三.代码 配置文件配置数据库,redis等相关的信息. # See http://docs.spring.io/sprin ...

  2. SpringBoot+MyBatis+Redis实现SSO单点登录系统(一)

    SpringBoot+MyBatis+Redis实现SSO单点登录系统(一) 一.SSO系统概述 SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可 ...

  3. sso单点登录系统(解决session共享)

    场景:假设一个用户将自己的登录信息提交到后台,如果session保存的信息分布在多台机器上,并且不共享,那么可能导致用户的登录信息出现短暂的丢失,为什么这样讲,因为用户访问服务器中间还要经过负载均衡服 ...

  4. 互联网分布式微服务云平台规划分析--SSO单点登录系统

    介绍 鸿鹄云架构[SSO单点登录系统]为所有微服务提供统一的用户认证服务,系统本身属于微服务模式,使用JWT+Redis分布式存储方案,确保不同微服务.系统之间的安全通讯和统一用户校验.认证.在整个服 ...

  5. Shiro整合SSO单点登录系统

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/m0_37797991/article/ ...

  6. 手撕一套sso(单点登录)系统之原理篇1

    在手撕之前,你首先要了解一些原理,我写的案例成品可以访问zauth,语言是Java8. 目录 1.关于Http 2.用户信息怎么存?存什么?存在哪? 2.1 使用前端存储技术Storage或index ...

  7. SSO单点登录系统的实战运用

    通用介绍 单点登录系统,简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.任何SSO框架都需要创建统一的认 ...

  8. sso单点登录系统的理解

    单点登录有两种方式,一种是跨域,一种是不跨域. 一:在不跨域的情况下, 只需要将cookie设置为顶域状态,即可以实现cookie的共享. 二:跨域登录 用户访问app系统,app系统是需要登录的,但 ...

  9. 基于cookie的SSO单点登录系统

    利用COOKIE实现单点登录功能 近期公司要求帮一个项目实现单点登录功能,在综合考量下决定采用cookie实现,大概的流程如下图所: 转载于:https://www.cnblogs.com/bugge ...

  10. SSO单点登录系统搭建(附源码)

最新文章

  1. SpringCloud 分布式事务解决方案
  2. Java实现余弦定理计算文本相似度
  3. Python计算机视觉:第九章 图像分割
  4. 在asp.net 2.0中使用SqlBulkCopy类迁移数据[转]
  5. (13)FPGA面试技能提升篇(Shell脚本)
  6. 【报告分享】2021年度中国计算机视觉人才调研报告-德勤.pdf(附下载链接)
  7. 整数类型及整数类型的显示转换
  8. UVA 12161 Ironman Race in Treeland
  9. html中表格table冻结行和列
  10. aidlearning开发python使用教程_极致安卓之—Aid Learning基于Jupyter开发Java和Python
  11. 小新想把百度搜索引擎改为edge
  12. 电子测量-不同电压波形对不同检波特性电压表的影响分析
  13. android svg 线条动画教程,简单的SVG线条动画
  14. 电信卡 LTE 无法短信发送
  15. 第二组第一次成团哈哈哈哈
  16. 基于单片机的电铃控制器
  17. 网络安全职业规划(笔记)
  18. NBA赛事直播超清画质背后:阿里云视频云「窄带高清2.0」技术深度解读
  19. STM32-APDS9960手势识别
  20. ubuntu-中文语言包无法下载

热门文章

  1. sstream和strstream的用法
  2. Linux攻关之基础模块七 命令总结
  3. 玩游戏用什么轴的机械键盘好_机械键盘吃鸡用什么轴好?玩绝地求生机械键盘键轴推荐...
  4. CSDN Markdown 显示连续两个中划线 --
  5. Ubuntu18.04提示adb设备没有权限
  6. 我的世界1.12.2java下载_我的世界Minecraft Java版1.12.2 pre2 宣布
  7. Vissim全网最全学习资料入口
  8. 静态库,动态库是啥,有啥区别(静态函数库/动态函数库)
  9. jdbc PreparedStatement中“?”报错
  10. MQTT Broker 比较与选型