前言

1.了解token模式:


token (令牌)是一串字符串,通常因为作为鉴权凭据,最常用的使用场景是 API 鉴权。
token 通过一次登录验证,得到一个鉴权字符串,然后以后带着这个鉴权字符串进行后续操作,这样就可以解决每次请求都要带账号密码的问题,而且也不需要反复使用账号和密码。

一、JWT是什么?

1.概念

JWT 全称 JSON Web Tokens ,是一种规范化的 token

2.组成

一个 JWT token 是一个字符串,它由三部分组成,头部、载荷与签名,中间用 . 分隔

(1)头部:用于存放token类型和加密协议,一般都是固定的

头部通常由两部分组成:
(1)令牌的类型(即 JWT)
(2)正在使用的签名算法(如 HMAC SHA256 或 RSA.)
json的形式:

{"alg": "HS256","typ": "JWT"
}

(2)载荷(Payload):存放用户数据

载荷中放置了 token 的一些基本信息,以帮助接受它的服务器来理解这个 token。同时还可以包含一些自定义的信息,用户信息交换。
载荷分为三类:预定义(官方注册说明使用);公有,私有。
预定义格式:建议不强制,可自定义

{"sub": "1","iss": "http://localhost:8000/auth/login","iat": 1451888119,"exp": 1454516119,"nbf": 1451888119,"jti": "37c107e4609ddbcc9c096ea5ee76c667","aud": "dev"
}

分别代表:

iss (issuer):签发人
sub (subject):主题
aud (audience):受众
exp (expiration time):过期时间
nbf (Not Before):生效时间,在此之前是无效的
iat (Issued At):签发时间
jti (JWT ID):编号

公有:也就是公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息,但不建议添加敏感信息,因为该部分在客户端可解密。

私有:也就是说私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。

(3)签名(Signature)

签名时需要用到前面编码过的两个字符串,如果以 HMACSHA256 加密,就如下:

HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret
)

加密后再进行 base64url 编码最后得到的字符串就是 token 的第三部分 zzzzz。
组合便可以得到 token:xxxxx.yyyyy.zzzzz。
签名的作用:保证 JWT 没有被篡改过,原理如下:
HMAC 算法是不可逆算法,类似 MD5 和 hash ,但多一个密钥,密钥(即上面的 secret)由服务端持有,客户端把 token 发给服务端后,服务端可以把其中的头部和载荷再加上事先共享的 secret 再进行一次 HMAC 加密,得到的结果和 token 的第三段进行对比,如果一样则表明数据没有被篡改。

二、JWT实战使用

JWT 的使用有两种方式:
加到 url 中:?token=你的token
加到 header 中,建议用这种,因为在 https 情况下更安全:Authorization:Bearer 你的token
(一般都是这种)

1.添加JWT依赖库

<dependencies><!-- JWT--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId></dependency>
</dependencies>

2.创建一个用户信息类

##实现这个接口:保证序列化,以流的形式在分布式系统中传播
public class UcenterMember implements Serializable {private static final long serialVersionUID = 1L;@ApiModelProperty(value = "会员id")@TableId(value = "id", type = IdType.ID_WORKER_STR)private String id;@ApiModelProperty(value = "微信openid")private String openid;@ApiModelProperty(value = "手机号")private String mobile;@ApiModelProperty(value = "密码")private String password;@ApiModelProperty(value = "昵称")private String nickname;@ApiModelProperty(value = "性别 1 女,2 男")private Integer sex;@ApiModelProperty(value = "年龄")private Integer age;@ApiModelProperty(value = "用户头像")private String avatar;@ApiModelProperty(value = "用户签名")private String sign;@ApiModelProperty(value = "是否禁用 1(true)已禁用,  0(false)未禁用")private Boolean isDisabled;@ApiModelProperty(value = "逻辑删除 1(true)已删除, 0(false)未删除")private Boolean isDeleted;@ApiModelProperty(value = "创建时间")@TableField(fill = FieldFill.INSERT)private Date gmtCreate;@ApiModelProperty(value = "更新时间")@TableField(fill = FieldFill.INSERT_UPDATE)private Date gmtModified;}

3.创建一个JwtTokenUtil工具类,用于创建token、验证token

public class JwtUtils {//常量public static final long EXPIRE = 1000 * 60 * 60 * 24; //token过期时间public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO"; //秘钥//生成token字符串的方法public static String getJwtToken(String id, String nickname){//头信息String JwtToken = Jwts.builder().setHeaderParam("typ", "JWT").setHeaderParam("alg", "HS256")
//设置超时时间.setSubject("guli-user").setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
//主体信息.claim("id", id)  //设置token主体部分 ,存储用户信息.claim("nickname", nickname)
//签名哈希,防伪标志.signWith(SignatureAlgorithm.HS256, APP_SECRET).compact();return JwtToken;}/*** 判断token是否存在与有效* @param jwtToken* @return*/public static boolean checkToken(String jwtToken) {if(StringUtils.isEmpty(jwtToken)) return false;try {Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 判断token是否存在与有效* @param request* @return*/public static boolean checkToken(HttpServletRequest request) {try {String jwtToken = request.getHeader("token");if(StringUtils.isEmpty(jwtToken)) return false;Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 根据token字符串获取会员id* @param request* @return*/public static String getMemberIdByJwtToken(HttpServletRequest request) {String jwtToken = request.getHeader("token");if(StringUtils.isEmpty(jwtToken)) return "";Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);Claims claims = claimsJws.getBody();return (String)claims.get("id");}
}

4.创建登录接口

(1)创建LoginVo用于数据封装

@Data
@ApiModel(value="登录对象", description="登录对象")
public class LoginVo {@ApiModelProperty(value = "手机号")private String mobile;@ApiModelProperty(value = "密码")private String password;
}

(2)创建controller编写登录方法

@RestController
@RequestMapping("/educenter/member")
@CrossOrigin
public class UcenterMemberController {@Autowiredprivate UcenterMemberService memberService;//登录@PostMapping("login")public R loginUser(@RequestBody UcenterMember member) {//member对象封装手机号和密码//调用service方法实现登录//返回token值,使用jwt生成String token = memberService.login(member);return R.ok().data("token",token);}//根据token获取用户信息@GetMapping("getMemberInfo")public R getMemberInfo(HttpServletRequest request) {//调用jwt工具类的方法。根据request对象获取头信息,返回用户idString memberId = JwtUtils.getMemberIdByJwtToken(request);//查询数据库根据用户id获取用户信息UcenterMember member = memberService.getById(memberId);return R.ok().data("userInfo",member);}//根据用户id获取用户信息@PostMapping("getUserInfoOrder/{id}")public UcenterMemberOrder getUserInfoOrder(@PathVariable String id) {UcenterMember member = memberService.getById(id);//把member对象里面值复制给UcenterMemberOrder对象UcenterMemberOrder ucenterMemberOrder = new UcenterMemberOrder();BeanUtils.copyProperties(member,ucenterMemberOrder);return ucenterMemberOrder;}
}

(3)创建service接口和实现类

@Service
public class UcenterMemberServiceImpl extends ServiceImpl<UcenterMemberMapper, UcenterMember> implements UcenterMemberService {@Autowiredprivate RedisTemplate<String,String> redisTemplate;//登录的方法@Overridepublic String login(UcenterMember member) {//获取登录手机号和密码String mobile = member.getMobile();String password = member.getPassword();//手机号和密码非空判断if(StringUtils.isEmpty(mobile) || StringUtils.isEmpty(password)) {throw new GuliException(20001,"登录失败");}//判断手机号是否正确QueryWrapper<UcenterMember> wrapper = new QueryWrapper<>();wrapper.eq("mobile",mobile);UcenterMember mobileMember = baseMapper.selectOne(wrapper);//判断查询对象是否为空if(mobileMember == null) {//没有这个手机号throw new GuliException(20001,"登录失败");}//判断密码//因为存储到数据库密码肯定加密的//把输入的密码进行加密,再和数据库密码进行比较//加密方式 MD5if(!MD5.encrypt(password).equals(mobileMember.getPassword())) {throw new GuliException(20001,"登录失败");}//判断用户是否禁用if(mobileMember.getIsDisabled()) {throw new GuliException(20001,"登录失败");}//登录成功//生成token字符串,使用jwt工具类String jwtToken = JwtUtils.getJwtToken(mobileMember.getId(), mobileMember.getNickname());return jwtToken;}}

总结

上述大致说明了jwt的简单使用,还有很多相关知识值得学习,上述实站只是提供了一个样例,仅供参考。

jwt实现单点登录,基础讲解加实战!!!相关推荐

  1. springBoot整合spring security+JWT实现单点登录与权限管理前后端分离

    在前一篇文章当中,我们介绍了springBoot整合spring security单体应用版,在这篇文章当中,我将介绍springBoot整合spring secury+JWT实现单点登录与权限管理. ...

  2. springBoot整合spring security+JWT实现单点登录与权限管理前后端分离--筑基中期

    写在前面 在前一篇文章当中,我们介绍了springBoot整合spring security单体应用版,在这篇文章当中,我将介绍springBoot整合spring secury+JWT实现单点登录与 ...

  3. [业务流程]JWT实现单点登录(SpringBoot + Vue +axious)

    JWT实现单点登录(SpringBoot + Vue +axious) 准备阶段: **登录所需对象** admin{ "username":"", //作为T ...

  4. 基于Spring Security与JWT实现单点登录

    基于RBAC的权限管理 RBAC(Role-Based Access Control):基于角色的访问控制 当前项目中,RBAC具体的表现为: 管理员表:ams_admin 角色表:ams_role ...

  5. JWT实现单点登录(sso)功能

    单点登录描述: 单点登录主要时应用在微服务架构中,在任意一个子服务中输入用户的用户名,密码进行登录时, 在跳转到其他系统的时候,就无需在进行登录,直接可以识别出用户的身份,权限以及角色等信息 . . ...

  6. Spring Cloud入门-Oauth2授权之基于JWT完成单点登录(Hoxton版本)

    文章目录 Spring Cloud入门系列汇总 摘要 单点登录简介 创建oauth2-client模块 修改授权服务器配置 网页单点登录演示 调用接口单点登录演示 oauth2-client添加权限校 ...

  7. SpringSecurity+OAuth2.0+JWT实现单点登录应用

    SpringSecurity+OAuth2.0+JWT实现单点登录应用 gitee项目练习地址:https://gitee.com/xzq25_com/springsecurity.oauth2 OA ...

  8. springsecurity oauth2使用jwt实现单点登录

    Jwt方式已经分享在文章结尾处的百度网盘链接中,redis方式可以看我以前发表的文章. 文章目录 前言 一.springsecurity oauth2 + redis方式的缺点 二.oauth2认证的 ...

  9. 漫画图解JWT设计单点登录系统

    JSON Web Token(JWT)是一个非常轻巧的规范.这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息. 让我们来假想一下一个场景.在A用户关注了B用户的时候,系统发邮件给B用户, ...

最新文章

  1. 阿里云蒋江伟:我们致力于为世界提供70%的算力 | 凌云时刻
  2. 为IP签发SSL证书
  3. 基于workerman实现的web消息推送站内信功能
  4. PowerDesigner 小工具窗
  5. mysql 1418 错误原因及解决
  6. PyTorch进行神经风格转换/迁移(Neural-Transfer:图像风格迁移)
  7. n!的位数的快速确定(斯特林公式)
  8. JVM插码之六:jacoco插码及问题“$jacocodata 属性 Method not found: is$jacocoData”
  9. HALCON示例程序classify_citrus_fruits.hdev应用常规gmm分类器进行水果分类
  10. 20组免费的用户界面图标,开发者必备
  11. Python就业涨薪小技巧!
  12. PTA : 函数题 7-3 两个有序链表序列的交集 (20 分)
  13. win7 mysql 未响应_求助啊 WIN7下安装mysql出问题 老是说未响应~!!
  14. 信噪比(dB)换算公式
  15. 写给零基础入坑蓝桥杯的同学
  16. 太漂亮了!有了3款开源图标库,不用再去求设计师了
  17. bash ps1变量_Linux:设置用户变量ps1
  18. 一张图架构示意图及简单分析
  19. 数字图像处理:图像几何变换(Matlab实现几何变换+原理解析
  20. 蚂蚁金服微贷事业群电话面试分享

热门文章

  1. Linux查询用户创建的后台程序
  2. windows 新建mysql权限设置_Windows下设置MySQL安全权限_mysql
  3. 快手用计算机说唱的叫什么,HIPHOP人物:“我们呢说唱,会在快手上爆炸!”
  4. 软件测试缺陷定义和管理
  5. 解决yum [Errno 256] No more mirrors to try
  6. 不设置DIV的宽高,让它相对于页面水平垂直居中
  7. Windows7系统下编译安装X264
  8. [Erlang危机](4.4)命名管道
  9. 深入浅出Mybatis系列(六)---objectFactory、plugins、mappers简介与配置[转]
  10. 标志寄存器操作(待续)