初识单点登录及JWT实现
单点登录
多系统,单一位置登录,实现多系统同时登录的一种技术
(三方登录:某系统使用其他系统的用户,实现本系统登录的方式。如微信登录、支付宝登录)
单点登录一般是用于互相授信的系统,实现单一位置登录,全系统有效
一、Session跨域
所谓 Session 跨域就是摒弃了系统提供的 Session ,而使用自定义的类似 Session 的机制来保存客户端数据的一种解决方案。
如:通过设置 cookie 的 domain 来实现 cookie 的跨域传递。在 cookie 中传递一个自定义的 session_id。这个 session_id 是客户端的唯一标记,将这个标记作为key,将客户需要保存的数据作为value,在服务端进行保存(数据库保存或nosql保存)。这种机制就是 Session 的跨域解决。
什么为跨域:客户端请求的时候,请求的服务器,不是同一个IP、端口、域名、主机名的时候,都称为跨域。
什么是域:在应用模型中,一个完整的、有独立访问路径的功能集合成为一个域。
如:百度称为一个应用或系统,其下有若干个域,如搜索引擎(www.baidu.com),百度贴吧(tie.baidu.com),百度知道(zhidao.baidu.com)等。
有时也称为多级域名。域的划分:以IP、端口、域名、主机名为标准,实现划分。
二、Spring Session 共享
spring-session 技术是 spring 提供的用于处理集群会话共享的解决方案。spring-session技术是将用户 session 数据保存到第三方容器中,如数据库。
Spring-session 技术是解决同域名下的多服务器集群 session 共享问题的,不能解决跨域 Session 共享问题
三、Nginx Session 共享
nginx中的 ip_hash 技术能够将某个 ip 的请求定向到同一台后端,这样一来这个ip下的某个客户端和某个后端就能建立起稳固的session,ip_hash是在upstream配置中定义的
四、Token身份认证
使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录,大概流程如下:
1)客户端使用用户名、密码请求登录
2)服务端收到请求、去验证用户名与密码
3)验证成功后,服务端会签发y一个 token ,再把这个 token 发送给客户端
4)客户端收到 token 以后可以把它存储起来,比如放在 cookie 里或者 Local Storage里
5)客户端每次向服务器请求资源的时候需要带着服务器签发的 token
6)服务端收到请求,然后去验证客户端请求里面带着的 token,如果验证成功,就向客户端返回请求的数据
使用token的优势:
无状态、可扩展:
在客户端存储的 token 是无状态的,并且能够被扩展,基于这种无状态和不存储session信息,负载均衡器能够将用户信息从一个服务传到其他服务器上。
安全性:
请求中发送token而不再发送cookie能够防止CSRF(跨域请求伪造)。即使在客户端使用cookie存储token。cookie也仅仅是一个存储机制而不是用于认证。
不将信息存储在session中,让我们少了对session的操作。
五、JSON Web Token(JWT)机制
JWT是一种紧凑且自包含的,用于在多方传递 json 对象的技术。传递的数据可以使用数字签名增加其安全性。可以使用HMAC加密算法或RSA公钥/私钥加密方式。
紧凑:数据小,可以通过URL、POST参数,请求头发送,且数据小代表传输速度快。
自包含:使用 payload 数据块j记录用户必要且不隐私的数据,可以有效的减少数据库访问次数,提高代码性能
JWT一般用于处理用户身份校验或数据信息交换
JWT的数据结构
JWT的数据结构:A.B.C 以.(点)来划分
A-header 头信息
B-payload (有效荷载?)
C-Signature 签名
header:
数据结构:{"alg":"加密算法名称","typ":"JWT"}
alg可以有 HMAC 或 SHA256 或 RSA 等
payload:主要分为三部分:已注册信息、公开数据、私有数据
singature:
签名信息,这是一个由开发者提供的信息。是服务器验证的传递的数据是否有效安全的标准。
执行流程
简单实现
1)造数据 JWTUsers模拟数据库用户名密码
package cn.zytao.taosir;import java.util.HashMap; import java.util.Map;/*** 用于模拟用户数据的,开发中应访问数据库验证用户* @author TAOSIR**/ public class JWTUsers {private static final Map<String,String> USERS =new HashMap<>(11);static {for(int i=0;i<10;i++) {USERS.put("admin"+i, "pwd"+i);}}//验证是否可以登录public static boolean isLogin(String username,String pwd) {if(null == username || username.trim().length()==0)return false;String obj=USERS.get(username);if(null ==obj||!obj.equals(pwd))return false;return true;} }
2)JWTSubject
package cn.zytao.taosir; /*** 作为Subject数据使用,也就是payload中保存的public claims* 其中不应包含任何敏感数据* 开发中建议使用实体类型,或BO,DTO数据对象* @author TAOSIR**/ public class JWTSubject {private String username;public JWTSubject() {super();}public JWTSubject(String username) {super();this.username = username;}public String getUsername() {return username;}public void setUsername(String username) {this.username=username;} }
3)JWT结果对象
package cn.zytao.taosir; /*** 作为Subject数据使用,也就是payload中保存的public claims* 其中不应包含任何敏感数据* 开发中建议使用实体类型,或BO,DTO数据对象* @author TAOSIR**/ public class JWTSubject {private String username;public JWTSubject() {super();}public JWTSubject(String username) {super();this.username = username;}public String getUsername() {return username;}public void setUsername(String username) {this.username=username;} }
4)响应对象
package cn.zytao.taosir;public class JWTResponseData {private Integer code;//返回码private Object data;//业务数据private String msg;//返回描述private String token;//身份标识public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public String getToken() {return token;}public void setToken(String token) {this.token = token;} }
5)JWT控制类
package cn.zytao.taosir; /*** JWT工具类* @author TAOSIR**/import java.util.Date;import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec;import com.fasterxml.jackson.databind.ObjectMapper;import io.jsonwebtoken.Claims; import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.SignatureException;public class JWTUtils {private static final String JWT_SECERT = "test_jwt_secert";//服务器的key,密钥private static final ObjectMapper MAPPER = new ObjectMapper();//用户java对象和json字符串转换public static final int JWT_ERRCODE_EXPIRE = 1005;//Token过期public static final int JWT_ERRCODE_FAIL = 1006;//验证不通过public static SecretKey generalKey() {try {byte[] encodedKey=JWT_SECERT.getBytes("UTF-8");SecretKey key=new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");return key;} catch (Exception e) {e.printStackTrace();return null;}}/*** 签发JWT,即创建token的方法* @param id jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击* @param iss jwt签发者* @param subject jwt所面向的用户,payload中记录的public,claims,当前环境中就是用户的登录名* @param ttlMills 有效期,单位毫秒* @return*/public static String createJWT(String id,String iss,String subject,long ttlMillis) {//加密算法SignatureAlgorithm signatureAlgorithm=SignatureAlgorithm.HS256;long nowMillis = System.currentTimeMillis();Date now=new Date(nowMillis);SecretKey secretKey=generalKey();//创建JWT的构造器用于生成tokenJwtBuilder builder=Jwts.builder().setId(id).setIssuer(iss).setSubject(subject).setIssuedAt(now).signWith(signatureAlgorithm, secretKey);if(ttlMillis >= 0) {long expMillis =nowMillis+ttlMillis;Date exDate = new Date(expMillis);builder.setExpiration(exDate);}return builder.compact();}/*** 验证JWT* @param jwtStr* @return*/public static JWTResult validateJWT(String jwtStr) {JWTResult checkResult=new JWTResult();Claims claims=null;try {claims=parseJWT(jwtStr);checkResult.setSuccess(true);checkResult.setClaims(claims);} catch (ExpiredJwtException e) {checkResult.setSuccess(false);checkResult.setErrCode(JWT_ERRCODE_EXPIRE);} catch (SignatureException e) {checkResult.setSuccess(true);checkResult.setErrCode(JWT_ERRCODE_FAIL);}return checkResult;}/*** 解析JWT字符串* @param jwt 就是token* @return*/public static Claims parseJWT(String jwt) {SecretKey secretKey=generalKey();//getBody获取值就是token中记录的payload数据,就是其中保存的claimsreturn Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();}/*** 生成subject信息* @param subObj* @return*/public static String generalSubject(Object subObj) {try {return MAPPER.writeValueAsString(subObj);} catch (Exception e) {e.printStackTrace();return null;}} }
6)写个简单的controller实践
package cn.zytao.taosir.controller;import java.util.UUID;import javax.servlet.http.HttpServletRequest;import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;import cn.zytao.taosir.JWTResponseData; import cn.zytao.taosir.JWTResult; import cn.zytao.taosir.JWTSubject; import cn.zytao.taosir.JWTUsers; import cn.zytao.taosir.JWTUtils;@RestController public class JWTController {@RequestMapping("testAll")public Object testAll(HttpServletRequest request) {String token=request.getHeader("Authorization");JWTResult result=JWTUtils.validateJWT(token);JWTResponseData responseData=new JWTResponseData();if(result.isSuccess()) {responseData.setCode(200);responseData.setData(result.getClaims().getSubject());String newToken=JWTUtils.createJWT(result.getClaims().getId(), result.getClaims().getIssuer(), result.getClaims().getSubject(), 1*60*1000);responseData.setToken(newToken);return responseData;}else {responseData.setCode(500);responseData.setMsg("用户未登录");return responseData;}}@RequestMapping("login")public Object login(String username,String password) {JWTResponseData responseData=null;//认证用户信息if(JWTUsers.isLogin(username, password)) {JWTSubject subject=new JWTSubject(username);String jwtToken = JWTUtils.createJWT(UUID.randomUUID().toString(),"sxt-test-jwt", JWTUtils.generalSubject(subject), 1*60*1000);responseData=new JWTResponseData();responseData.setCode(200);responseData.setData(null);responseData.setMsg("登录成功");responseData.setToken(jwtToken);}else {responseData=new JWTResponseData();responseData.setCode(500);responseData.setData(null);responseData.setMsg("登录失败");responseData.setToken(null);}return responseData;} }
7)Postman查看情况
转载于:https://www.cnblogs.com/it-taosir/p/10021811.html
初识单点登录及JWT实现相关推荐
- 尚硅谷2020微服务分布式电商项目《谷粒商城》-单点登录(jwt)
学习更多的知识,整理不易,拒绝白嫖,记得三连哦 关注公众号:java星星 获取全套课件资料 1. 用户管理提供数据接口 1.1. 数据验证功能 根据接口文档知: 请求方式:GET 请求路径:check ...
- 单点登录CAS学习(一):初识单点登录
一.单点登录应用场景 不少业主单位随着自身的发展,建立不少业务支撑系统,往往会采用不同的开发商进行系统开发和建设,因此必然形成如下一种局面:工作人员需要登录多个业务系统才能将自己的工作全部完成,给工作 ...
- 单点登录-基于JWT机制的单点登录
1.认证过程 登录: 1)第一次认证:第一次登录,用户从浏览器输入用户名/密码,提交后到服务器的登录处理的Action层(Login Action): 2)Login Action调用认证服务进行用户 ...
- SSO单点登录之——JWT
//JWT核心依赖<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</ar ...
- JWT实现单点登录(SSO)
目录 一.理论 1.SSO 2.JWT #.组成 #.如何工作 3.Redis RSA MD5 4.AOP 二.实现过程 #.准备工作 #.登录 #.测试类 #.插拔式注解 #.测试 最近有机 ...
- JSON Web Token (JWT)笔记(token实现单点登录功能)
文章目录 前情提要 cookie(储存在用户本地终端上的数据) Cookie特点: session(web服务端内存) cookie和session 单点登录(只登录一次,可使用账号下全部服务)三种方 ...
- springboot整合soo单点登录
简介单点登录(Soo) 使用token技术完成单点登录 使用jwt规则创建token 导入依赖 <!-- JWT--><dependency><groupId>io ...
- CAS单点登录(一)——初识SSO
前言:其实好早就想把CAS的这一套知识整合一下,在工作上也应用到了这块,只是最近才在工作上接触到CAS,所以刚好把这些知识总结一下.这块可能是一个比较大的模块知识点,所以会有多篇文章进行逐一展开,笔者 ...
- java oauth sso 源码_基于Spring Security Oauth2的SSO单点登录+JWT权限控制实践
概 述 在前文<基于Spring Security和 JWT的权限系统设计>之中已经讨论过基于 Spring Security和 JWT的权限系统用法和实践,本文则进一步实践一下基于 Sp ...
最新文章
- springboot集合jpa使用
- springboot中如何获取yml配置文件中的配置信息
- 机器学习(一)线性回归
- VC中海量文件读写类设计与应用(转)
- 硬件:笔记本常见故障处理技巧与思路,值得收藏!
- java演练代码 银行取款演练 java
- 计算机偏门术语,没听说过 WinXP偏门应用技巧四则
- symfony api 异常处理_dubbo-RPC服务的异常处理
- GridView表头排序方法设置
- CentOS 6.9之LVM创建,扩容
- time datetime的时间--python
- 兰光bl2000_蓝光bl2000电梯主板.pdf
- STM32F407 + Codec AK4556 + NAND Flash MX30LF2G 录音机实现
- 家用宽带搭建个人服务器(一)
- 车势科技发力汽车VR,继阿里BUY+之后再现VR购物挑战者
- 面对全面收紧外链的微信,H5的春风还能吹多久?
- Embedding Propagation: Smoother Manifold for Few-Shot Classification ECCV 2020
- 论文阅读_Spatial Temporal Graph Convolutional Networks for Skeleton-Based Action Recognition
- margin属性的正负值确定
- Android手电筒介绍
热门文章
- redis的那种目录结构能新建么_Serverless 解惑——函数计算如何访问 Redis 数据库...
- python安装多少位_python安装流程
- 2108年计算机二级考试时间,计算机二级office考前10天复习应该做哪些安排逢考必过...
- socket 收不到netty客户端消息_Netty开发 —— 首个demo学习
- 信息竞赛进阶指南--单调栈(模板)
- Codeforces 1323 div2题解ABC
- [多图/秒懂]白话OpenPose,最受欢迎的姿态估计网络
- android人脸识别技术浅析
- 以太网供电技术/有源以太网技术POE简单介绍
- Windows 下各种Python库的下载与安装