DartVM服务器开发(十六)-Jaguar使用JWT

今天我们来学习一下jaguar如何使用JWT!

1.JWT是什么?

学习如何使用之前,我们来了解一下什么是JWT

JWT(Json Web Token)Json网络令牌,是基于Json的开放标准,是一个用私钥编码和签名的JSON数据,由于它已签名,因此无法篡改数据。在存在私钥的情况下,可以跨多个服务器验证数据(用于完整性和真实性)。
JWT令牌有三部分:

  • Header
    包含用于对令牌签名的算法,用于声明类型typ和加密算法alg,该内容使用base64加密

    1
    2
    3
    4
    {
    "typ": "JWT",
    "alg": "HS256"
    }
  • Body
    主要为json数据,该数据经过Base64URl编码,包含声明

    • 标准声明(建议使用)
      iss: jwt签发者
      sub: jwt所面向的用户
      aud: 接收jwt的一方
      exp: jwt的过期时间,这个过期时间必须要大于签发时间
      nbf: 定义在什么时间之前,该jwt都是不可用的.
      iat: jwt的签发时间
      jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
    • 公有声明
      该部分可添加任何信息
    • 私有声明
      客户端与服务端共同定义的声明
  • Signature
    根据算法,签名包含使用私钥签名的正文签名
    =header.alg(base64UrlEncode(header) + "." + base64UrlEncode(body))*私钥

    ok,我们了解了什么是JWT, 下面我们开始使用

    2.Jaguar使用JWT

  • 添加依赖

    pubspec.yaml文件下添加下面内容
    1
    2
    3
    dependencies:
    #....
    jaguar_jwt: ^2.1.5

然后运行pub get
成功.png
可以看到,没有任何问题

  • 导入包

    我们在main.dart文件下面导入包

    1
    import 'package:jaguar_jwt/jaguar_jwt.dart';
  • 使用

    首先我们来声明一个私钥key

    1
    final key ='rhymelph123flutterdartvmser';

然后添加body

1
2
3
4
5
6
7
8
9
final JwtClaim jwtClaim=new JwtClaim(
subject: 'rhyme',//发明者
issuer: 'jaguar',//发行的令牌
issuedAt: DateTime(2018,9,4,11,11),//发行的时间
expiry: DateTime(2018,9,6),//令牌到期时间
jwtId: '1',//唯一id
audience: ['ben','jack'],//令牌受众者
payload: { "data":"数据",},
);

根据bodykey生成token,这里的大部分处理,jaguar_jwt都帮你处理好了

1
String token = issueJwtHS256(jwtClaim, key);

通过tokenkey获取JwtClaim

1
final jwtClaim=verifyJwtHS256Signature(token, key);

3. 实战

下面,我会通过登陆功能使用JWT
我们先定义两个接口,分别都使用post方式进行请求

  • /api/User/Login 登陆,传入账号和密码
  • /api/User/Info 获取用户信息,根据传入的token
    好了,接口有了,我们定义一个工具类,专门返回json数据
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    import 'dart:convert';

    ApiJson apiJson = new ApiJson();

    class ApiJson {

    String success() =>
    json.encode(new Api()
    ..code = 0
    ..msg = 'success'
    ..data = null,);

    Api successA() =>
    new Api()
    ..code = 0
    ..msg = 'success'
    ..data = null;


    String successResult(Object data) =>
    json.encode(new Api()
    ..code = 0
    ..msg = 'success'
    ..data = data,);

    Api successResultA(Object data) =>
    new Api()
    ..code = 0
    ..msg = 'success'
    ..data = data;


    String error() =>
    json.encode(new Api()
    ..code = -1
    ..msg = '未知错误'
    ..data = null);

    Api errorA() =>
    new Api()
    ..code = -1
    ..msg = '未知错误'
    ..data = null;

    String errorMsg(int code, String msg) =>
    json.encode(new Api()
    ..code = code
    ..msg = msg
    ..data = null);

    Api errorMsgA(int code, String msg) =>
    new Api()
    ..code = code
    ..msg = msg
    ..data = null;
    }

    class Api<T> {
    int code;
    String msg;
    T data;

    Map toMap() =>
    {
    "code": code,
    "msg": msg,
    "data": data,
    };
    }

登陆接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
..post('/api/User/Login', (ctx) async{
Map<String,String> params=await ctx.bodyAsUrlEncodedForm();
String username=params['username'];
String password=params['password'];
if(username.isEmpty||password.isEmpty){
//用户名或密码为空
return Response.json(apiJson.errorMsgA(-1, '用户名或密码为空!').toMap());
}else{
//在数据库中查询用户名
User user=await userBean.findOneWhere(userBean.username.eq(username));
if(user==null || user.password!=password){
//用户名或密码不正确
return Response.json(apiJson.errorMsgA(-2, '用户名或密码不正确!').toMap());
}else{
//正确,返回一个token信息
final JwtClaim jwtClaim=new JwtClaim(
subject: 'rhyme',//发明者
issuer: 'jaguar',//发行的令牌
issuedAt: DateTime(2018,9,4,11,11),//发行的时间,这里的时间应该是当前时间
expiry: DateTime(2018,9,6),//令牌到期时间,该时间应该在发行时间加一两天
jwtId: '1',//唯一id
audience: ['ben','jack'],//令牌受众者
payload: user.toMap(),
);

String token=issueJwtHS256(jwtClaim, key);
return Response.json(apiJson.successResultA(token).toMap());
}
}
})

获取用户信息接口

1
2
3
4
5
6
..post('/api/User/Info', (ctx) async{
Map<String,String> params=await ctx.bodyAsUrlEncodedForm();
String token=params['token'];
final jwtClaim=verifyJwtHS256Signature(token, key);
return Response.json(jwtClaim.payload);
})

下面我们来请求一下吧!
登陆.png
请求用户信息.png

可以看到,我们成功的使用了JWT,好了,今天的内容就到这里了,我们明天见!

评论系统未开启,无法评论!