共计 3627 个字符,预计需要花费 10 分钟才能阅读完成。
概念
单点登录 (SingleSignOn,SSO),就是通过用户的一次性甄别登录。 当用户在身份认证服务器上登录一次当前,即可取得拜访单点登录零碎中其余关联系统和应用软件的权限,这种形式缩小了由登录产生的工夫耗费,辅助了用户治理,是目前比拟风行的 一种登录形式
业务场景
要求用户只须要登录一次, 那么就能够拜访其余的认证零碎, 无需用户再次登录.
如果登录信息都保留在各自的服务器上, 则必然会呈现用户频繁登录的景象.
单点登录实现策略
步骤:
1. 当用户输出用户名和明码时须要将数据传递给 jt-web 服务器进行登录操作.
2.jt-web 服务器须要将数据传到 jt-sso 服务器中进行数据的校验.
3.jt-sso 依据 username/password 查询数据库校验数据是否无效.
4. 如果用户名和明码正确则将数据通过解决之后保留到 redis 中 KEY=UUID(每次生成的都不一样) VALUE=“userJSON”
5. 如果用户写入 redis 胜利, 之后须要将用户的登录的凭证返回给客户端.
6.JT-WEB 服务器将获取的 TICKET 信息保留到客户端的 Cookie 中, 不便下次应用. 并且要求 cookie 共享 的.
cookie
因为不能将信息存在服务器的 session 中, 所以 cookie 就是单点登录实现的要害.
概念
- Cookie 是将会话中产生的数据保留在客户端,是客户端技术。
- Cookie 是基于两个头进行工作的:别离是 Set-Cookie 响应头和 Cookie 申请头
- 通过 Set-Cookie 响应头将 cookie 从服务器端发送给浏览器,让浏览器保留到外部;而浏览器一旦保留了 cookie,当前浏览器每次拜访服务器时,都会通过 cookie 申请头,将 cookie 信息再带回服务器中。在须要时,在服务器端能够获取申请中的 cookie 中的数据,从而实现某些性能。
cookie API
1. 创立 Cookie 对象
Cookie c = new Cookie(String name, String value);
// 创立 cookie 的同时须要指定 cookie 的名字和 cookie 要保留的值
// Cookie 的名字一旦指定后,就无奈批改!
2. 将 Cookie 增加到 response 响应中
response.addCookie(Cookie c);
// 将 cookie 增加到响应中,由服务器负责将 cookie 信息发送给浏览器,再由浏览器保留到外部(能够屡次调用该办法,增加一个以上的 cookie)
3. 获取申请中的所有 cookie 对象组成的数组
Cookie[] cs = request.getCookies();
// 获取申请中携带的所有 cookie 组成的 cookie 对象数组,如果申请中没有携带任何 cookie,调用该办法会返回 null。
4. 删除浏览器中的 Cookie
cookie 的 API 中没有提供间接删除 cookie 的办法,能够通过别的形式间接删除 cookie
删除名称为 cart 的 cookie:能够向浏览器再发送一个同名的 cookie(即名称也叫做 cart),并设置 cookie 的最大生存工夫为零,因为浏览器是依据 cookie 的名字来辨别 cookie,如果前后两次向浏览器发送同名的 cookie,后发送的 cookie 会笼罩之前发送的 cookie。而后发送的 cookie 设置了生存工夫为零,因而浏览器收到后也会立刻删除!
// 创立一个名称为 cart 的 cookie
Cookie c = new Cookie("cart", "");
// 设置 cookie 的最大生存工夫为零
c.setMaxAge(0);
// 将 cookie 增加到响应中, 发送给浏览器
response.addCookie(c);
out.write("胜利删除了名称为 cart 的 cookie...");
5.Cookie 的罕用办法
cookie.getName(); // 获取 cookie 的名字
cookie.getValue(); // 获取 cookie 中保留的值
cookie.setValue(); // 设置 / 批改 cookie 中保留的值(没有 setName 办法, 因为 cookie 的名字无奈批改)
cookie.setMaxAge(); // 设置 cookie 的最大生存工夫(如果不设置,cookie 默认在一次会话完结时销毁!)
6.setMaxAge 办法 :设置 cookie 的最大生存工夫
如果不设置该办法,cookie 默认是会话级别的 cookie,即生存工夫是一次会话。当浏览器敞开,会话完结时,cookie 也会被销毁(cookie 默认存在浏览器的内存中,当浏览器敞开,内存开释,cookie 也会随着内存的开释而销毁。)
如果设置了该办法,cookie 将不会保留到浏览器的内存中,而是以文件模式保留到浏览器的长期文件夹中(也就是硬盘上),这样再敞开浏览器,内存开释,保留到硬盘上的 cookie 文件不会销毁,再次关上浏览器,还能够获取硬盘上的 cookie 信息。
实例
前端 controller 层
/**
* 实现用户的登录操作
* url 地址:http://www.jt.com/user/doLogin?r=0.8989367429030823
* 参数: username/password
* 返回值: SysResult 对象 的 JSON 的数据.
*
* cookie.setMaxAge(-1); 敞开浏览器会话时删除
* cookie.setMaxAge(0); 立刻删除 cookie
* cookie.setMaxAge(100); cookie 能够存储的工夫单位是秒
*
* http://www.jt.com/saveUser/xxx
* cookie.setPath("/");
* cookie.setPath("/add");
*/
@RequestMapping("/doLogin")
@ResponseBody
public SysResult doLogin(User user, HttpServletResponse response){
//1. 实现用户的登录操作!!!
String ticket = dubboUserService.doLogin(user);
//2. 校验 ticket 是否有值.
if(StringUtils.isEmpty(ticket)){
// 用户名或者明码谬误
return SysResult.fail();}
//3. 如果用户的 ticket 不为 null, 则示意登录正确, 须要将数据保留到 cookie 中
//Cookie 要求 1.7 天无效 2. 要求 cookie 能够在 jt.com 的域名中共享 3.cookie 权限 /
Cookie cookie = new Cookie("JT_TICKET",ticket);
cookie.setMaxAge(7*24*3600);
cookie.setDomain("jt.com"); // 在 jt.com 中实现页面共享.
cookie.setPath("/"); // 定于 cookie 的权限根目录无效
response.addCookie(cookie); // 利用 response 将 cookie 保留到客户端中.
return SysResult.success();}
后端 service 实现类
/**
* 1. 依据用户名和明码查询数据库
* 2. 校验用户数据的有效性.
* 3. 如果用户的数据是正确的 则开始进行单点登录操作.
* 4. 如果用户数据不正确 则 ticket 数据为 null 即可.
* @param user
* @return
*/
@Override
public String doLogin(User user) {
//1. 将明码进行加密解决
String password = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
user.setPassword(password);
// 如果传递的是对象, 则依据对象中不为 null 的属性充当 where 条件
QueryWrapper<User> queryWrapper = new QueryWrapper<>(user);
User userDB = userMapper.selectOne(queryWrapper);
//2. 校验数据是否无效
if(userDB == null){return null;}
//userDB 数据不为 null, 用户的输出信息正确. 开启单点登录操作.
//3.1 动静生成 uuid
String ticket = UUID.randomUUID().toString().replace("-", "");
//3.2 脱敏解决
userDB.setPassword("123456 你信不??");
String userJSON = ObjectMapperUtil.toJSON(userDB);
//3.3 将数据保留到 redis 中
jedisCluster.setex(ticket, 7*24*60*60, userJSON);
return ticket;
}
前后端通过 dubbo 以及公共接口调用.