详解JWT token心得与使用实例


Posted in Javascript onAugust 02, 2019

本文你能学到什么?

token的组成
token串的生成流程。
token在客户端与服务器端的交互流程
Token的优点和思考
参考代码:核心代码使用参考,不是全部代码

JWT token的组成

头部(Header),格式如下:

{ 
“typ”: “JWT”, 
“alg”: “HS256” 
}

由上可知,该token使用HS256加密算法,将头部使用Base64编码可得到如下个格式的字符串:

eyJhbGciOiJIUzI1NiJ9

有效载荷(Playload):

{ 
“iss”: “Online JWT Builder”, 
“iat”: 1416797419, 
“exp”: 1448333419, 
……. 
“userid”:10001 
}

有效载荷中存放了token的签发者(iss)、签发时间(iat)、过期时间(exp)等以及一些我们需要写进token中的信息。有效载荷也使用Base64编码得到如下格式的字符串:

eyJ1c2VyaWQiOjB9

签名(Signature):

将Header和Playload拼接生成一个字符串str=“eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyaWQiOjB9”,使用HS256算法和我们提供的密钥(secret,服务器自己提供的一个字符串)对str进行加密生成最终的JWT,即我们需要的令牌(token),形如:str.”签名字符串”。

token在服务与客户端的交互流程

1:客户端通过用户名和密码登录
2:服务器验证用户名和密码,若通过,生成token返回给客户端。
3:客户端收到token后以后每次请求的时候都带上这个token,相当于一个令牌,表示我有权限访问了
4:服务器接收(通常在拦截器中实现)到该token,然后验证该token的合法性(为什么能验证下面说)。若该token合法,则通过请求,若token不合法或者过期,返回请求失败。

关于Token的思考

服务如何判断这个token是否合法?

由上面token的生成可知,token中的签名是由Header和有效载荷通过Base64编码生成再通过加密算法HS256和密钥最终生成签名,这个签名位于JWT的尾部,在服务器端同样对返回过来的JWT的前部分再进行一次签名生成,然后比较这次生成的签名与请求的JWT中的签名是否一致,若一致说明token合法。由于生成签名的密钥是服务器才知道的,所以别人难以伪造。

token中能放敏感信息吗?
不能,因为有效载荷是经过Base64编码生成的,并不是加密。所以不能存放敏感信息。

Token的优点

(1)相比于session,它无需保存在服务器,不占用服务器内存开销。
(2)无状态、可拓展性强:比如有3台机器(A、B、C)组成服务器集群,若session存在机器A上,session只能保存在其中一台服务器,此时你便不能访问机器B、C,因为B、C上没有存放该Session,而使用token就能够验证用户请求合法性,并且我再加几台机器也没事,所以可拓展性好就是这个意思。
(3)由(2)知,这样做可就支持了跨域访问。

Java实例:JWT token使用

部分代码来自互联网,找不到原作者了。。

编写JWT(Java Web Token)操作类:JavaWebToken

public class JavaWebToken {

  private static Logger log = LoggerFactory.getLogger(JavaWebToken.class);

  //该方法使用HS256算法和Secret:bankgl生成signKey
  private static Key getKeyInstance() {
    //We will sign our JavaWebToken with our ApiKey secret
    SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
    byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary("bankgl");
    Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
    return signingKey;
  }

  //使用HS256签名算法和生成的signingKey最终的Token,claims中是有效载荷
  public static String createJavaWebToken(Map<String, Object> claims) {
    return Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS256, getKeyInstance()).compact();
  }

  //解析Token,同时也能验证Token,当验证失败返回null
  public static Map<String, Object> parserJavaWebToken(String jwt) {
    try {
      Map<String, Object> jwtClaims =
          Jwts.parser().setSigningKey(getKeyInstance()).parseClaimsJws(jwt).getBody();
      return jwtClaims;
    } catch (Exception e) {
      log.error("json web token verify failed");
      return null;
    }
  }
}

编写登录Conreoller,在服务器端给客户返回token.

public LoginStatusMessage checkUserAndPassword(
  @RequestParam(value="username",required=true) String username,
  @RequestParam(value="password",required=true) String password,User user,HttpServletRequest request) throws Exception{
    User u = new User();
    //登录成功
    if((u = userService.checkUsernameAndPassword(user)) != null){
      Map<String,Object> m = new HashMap<String,Object>();
      m.put("userid", user.getUserid());
      String token = JavaWebToken.createJavaWebToken(m);
      System.out.println(token);
      LoginStatusMessage lsm = new LoginStatusMessage();
      lsm.setUser(u);
      lsm.setToken(token);
      return lsm;
    };
    //登录失败,返回Null
    return null;
  }

在拦截器中对请求中的Token验证(部分代码,表示下意思):

String token = request.getParameter("token");
      if(JavaWebToken.parserJavaWebToken(token) != null){
        //表示token合法
        return true;
      }else{
        //token不合法或者过期
        return false;
      }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery实现类似滑动门切换效果的层切换
Sep 23 Javascript
点击按钮自动加关注的代码(sina微博/QQ空间/人人网/腾讯微博)
Jan 02 Javascript
Node.js中使用mongoskin操作mongoDB实例
Sep 28 Javascript
JQuery解析XML数据的几个简单实例
May 18 Javascript
Node.js开发教程之基于OnceIO框架实现文件上传和验证功能
Nov 30 Javascript
轻松实现jQuery添加删除按钮Click事件
Mar 13 Javascript
React为 Vue 引入容器组件和展示组件的教程详解
May 03 Javascript
基于Koa2写个脚手架模拟接口服务的方法
Nov 27 Javascript
vue draggable resizable gorkys与v-chart使用与总结
Sep 05 Javascript
微信小程序scroll-view点击项自动居中效果的实现
Mar 25 Javascript
Vue中 axios delete请求参数操作
Aug 25 Javascript
jquery实现图片放大镜效果
Dec 23 jQuery
详解使用JWT实现单点登录(完全跨域方案)
Aug 02 #Javascript
基于mpvue的简单弹窗组件mptoast使用详解
Aug 02 #Javascript
vue下使用nginx刷新页面404的问题解决
Aug 02 #Javascript
超轻量级的js时间库miment使用解析
Aug 02 #Javascript
操作按钮悬浮固定在微信小程序底部的实现代码
Aug 02 #Javascript
微信小程序中悬浮窗功能的实现代码
Aug 02 #Javascript
微信小程序的授权实现过程解析
Aug 02 #Javascript
You might like
php中CI操作多个数据库的代码
2012/07/05 PHP
成为好程序员必须避免的5个坏习惯
2014/07/04 PHP
PHP实现的一致性哈希算法完整实例
2015/11/14 PHP
ThinkPHP中limit()使用方法详解
2016/04/19 PHP
浅谈php fopen下载远程文件的函数
2016/11/18 PHP
北京奥运官方网站幻灯切换效果flash版打包下载
2008/01/30 Javascript
JavaScript中的排序算法代码
2011/02/22 Javascript
40个新鲜出炉的jQuery 插件和免费教程[上]
2012/07/24 Javascript
node.js中的fs.fchmod方法使用说明
2014/12/16 Javascript
js实现照片墙功能实例
2015/02/05 Javascript
JavaScript必知必会(七)js对象继承
2016/06/08 Javascript
jQuery实现的placeholder效果完整实例
2016/08/02 Javascript
浅谈AngularJS中使用$resource(已更新)
2017/09/14 Javascript
基于匀速运动的实例讲解(侧边栏,淡入淡出)
2017/10/17 Javascript
微信小程序实现之手势锁功能实例代码
2018/07/19 Javascript
angularJs中$http获取后台数据的实例讲解
2018/08/08 Javascript
对 Vue-Router 进行单元测试的方法
2018/11/05 Javascript
微信小程序分包加载代码实现方法详解
2019/09/23 Javascript
python 基础学习第二弹 类属性和实例属性
2012/08/27 Python
python 处理dataframe中的时间字段方法
2018/04/10 Python
python的pandas工具包,保存.csv文件时不要表头的实例
2018/06/14 Python
详解django中url路由配置及渲染方式
2019/02/25 Python
Python数据类型之String字符串实例详解
2019/05/08 Python
python查找重复图片并删除(图片去重)
2019/07/16 Python
解决django 新增加用户信息出现错误的问题
2019/07/28 Python
Python多进程编程常用方法解析
2020/03/26 Python
django模板获取list中指定索引的值方式
2020/05/14 Python
Pycharm自动添加文件头注释和函数注释参数的方法
2020/10/23 Python
GAP阿联酋官网:GAP UAE
2017/11/30 全球购物
Giglio英国站:意大利奢侈品购物网
2018/03/06 全球购物
卫校护理专业毕业生求职信
2013/11/26 职场文书
期中考试反思800字
2014/05/01 职场文书
学生夜不归宿检讨书
2014/09/23 职场文书
毕业论文指导教师评语
2014/12/30 职场文书
新郎答谢词
2015/01/04 职场文书
总经理助理岗位职责
2015/01/31 职场文书