DartVM服务器开发(二十四)--用户验证(jaguar_session_jwt)

今天我们来学习一下如何通过jaguar_session_jwt进行用户的验证!

1.导包

在我们的pubspec.yaml文件下添加下面代码

1
2
dependencies:
jaguar_session_jwt: ^2.2.1

然后执行pub get命令
pub get.png
导入文件

1
import 'package:jaguar_session_jwt/jaguar_session_jwt.dart';

这里要注意,使用该包,需要配合jaguar_jwtjaguar_auth这两个包使用

2,使用

  • 1.对用户模型进行处理,让用户模型实现PasswordUser接口

    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
    class User implements PasswordUser{
    @PrimaryKey()
    String id;//id号
    @Column(length: 20,isNullable: false)
    String username;//用户名
    @Column(length: 30,isNullable: false)
    String password;//密码
    @Column(isNullable: false)
    bool isUse;//是否可用
    String created;
    @HasOne(AvatarBean)
    Avatar avatar;//头像
    @Column(isNullable: true)
    String role;
    @Column(length: 11,isNullable: true)
    String phoneNumber;//电话号码
    @Column(length: 30,isNullable: true)
    String email;//邮箱
    @Column(length: 200,isNullable: true)
    String sign;//签名
    @Column(isNullable: true)
    String city;//城市

    //表名
    static const String tableName='_user';
    //new
    @override//授权身份验证
    String get authorizationId => id;
    //new
    }

    上面就是我今天用到的一个用户模型,内容还是很丰富的,可以注意到一个点,就是需要实现获取authorizationId,我传入的是用户的idPasswordUser还有一个password需要实现,但是我已经定义好了,所以,不用再实现了,

  • 2.定义一个用户提取器

    该用户取样器,是当用户登陆时,会通过该取样器去校验是否正确

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    import 'dart:async';
    import 'package:jaguar/jaguar.dart';

    class DummyUserFetcher implements UserFetcher<User> {
    final UserBean userBean;

    const DummyUserFetcher(UserBean userBean,)
    : userBean = userBean ;

    //身份验证
    Future<User> byAuthenticationId(Context ctx, String authenticationId) async =>
    await userBean.findOneWhere(userBean.username.eq(authenticationId));

    //授权书
    Future<User> byAuthorizationId(Context ctx, String sessionId) async =>
    await userBean.find(sessionId);
    }

上面通过两个地方进行对用户的校验,一个是用户名,一个是用户id,用户id一般存在session里面,有小伙伴可能会对authenticationIdauthorizationId混淆,仔细看是两个东西来的,一个是认证id,一个是授权id
ok,我们已经定义好了,下面是配置jwt

  • 3.配置jwt

    1
    const JwtConfig config=const JwtConfig(key);

上面传入一个key,一般为27位秘钥,自己定义好就行,什么都可以,JwtConfig还可以传入下面的字段

  • String Issuer 发行人
  • List audience 受众
  • Duration maxAge 过期时间,默认一天

像这样使用

1
2
3
4
5
const JwtConfig config=const JwtConfig(
key
,issuer: 'rhyme'
,audience: ['ben','jack']
,maxAge: Duration(days: 7));

  • 4. 配置服务器

    将上面已经配置好的jwt配置到服务器
    1
    2
    3
    4
    5
    6
    7
    main{
    dbmg.init();
    new Jaguar(sessionManager: JwtSession(config,io: SessionIoCookie()),)
    ..userFetchers[User]=DummyUserFetcher(new UserBean(dbmg.pgAdapter))
    ..add((reflect(UserController(dbmg.pgAdapter,cache))))
    ..serve(logRequests: true);
    }

如果有看过我之前的文章应该知道UserBean,pgAdapter,cache是什么吧,分别是Userdao类,数据库持有类,缓存 ,我们来重点讲一下JwtSession

  • config上面jwt配置
  • io 该参数可以传入SessionIoCookie()令牌存在cookie, SessionIoAuthHeader()令牌在授权头,SessionIoHeader令牌在头(请求头与应答头)
  • validationConfig 该参数为验证配置,用于验证令牌中的发行人与受众,所以,需要传入发行人与受众

详细说明一下io这个参数吧

  • SessionIoCookie(cookieName: 'token',cookiePath: '/he'),令牌自动放入到token这个键对应的值中,/he为路径,一般用于网页
    image.png

  • SessionIoAuthHeader(scheme: 'rhyme'),令牌放入到应答头中的authorizationrhyme拼接令牌
    image.png

  • SessionIoHeader(name: 'token'),令牌放入到应答头中对应传入的键中
    image.png

5.登陆用户

下面我们来写一个登陆接口

1
2
3
4
5
6
7
8
  @Post(path: '/login')
loginx(Context ctx) async{
//验证用户,并给予令牌
final User user=await FormAuth.authenticate<User>(ctx);
//返回用户信息
return Response.json((restful.ok_r()
..data=user).toMap(new UserSerializer()));
}

也可以这样写

1
2
3
4
5
6
7
@Post(path: '/login')
@Intercept(const [const FormAuth<User>()])
loginx(Context ctx) {
final User user=ctx.getVariable<User>();
return Response.json((restful.ok_r()
..data=user).toMap(new UserSerializer()));
}

FormAuth用于验证表单请求,编码题必须为application/x-www-form-urlencoded
FormAuth()构造方法可传入下面的参数

  • UserFetcher<UserModel> userFetcher 用户提取器,跟上面一样,默认使用服务器配置的
  • String authorizationIdKey 授权字段,默认为id
  • bool manageSession如果为false,则需要手动完成会话的创建,默认为true
  • Hasher hasher用于密码校验,默认为NoHasher()不需要校验

重点讲解下 Hasher hasher,当服务器接收到用户名username跟密码password,如果密码是加密过的,就可以使用该参数,它支持的参数

  • NoHasher()不需要进行校验
  • MD5Hasher(salt) md5校验,salt为盐值
  • Sha1Hasher(salt) Sha1校验,salt为盐值
  • Sha256Hasher(salt)Sha256校验,salt为盐值

同样的,还可以支持下面的请求

基本认证

1
2
@Post(path: '/login')
loginb(Context ctx) async => await BasicAuth.authenticate<User>(ctx);

上面的请求是将usernamepassword经过:username:password拼接后通过base64加密放入到
请求头的authorization对应的Basic键中

json认证

1
2
3
@PostJson(path: '/login')
@Intercept(const [const JsonAuth<User>()])
User login(Context ctx) => ctx.getVariable<User>();

6.授权访问

当用户登陆后,我们需要登陆后才能操作

1
2
3
4
5
@Post(path: '/hello')
@Intercept(const [Authorizer<User>()])
hello(Context ctx){
return Response.json('hello');
}

我们这里如果是用户没有登陆,会提示用户去进行登陆,登陆过后,柴可以访问hello接口

7.退出登录

1
2
3
4
5
@Post(path: '/logout')
logout(Context ctx)async{
(await ctx.sessions).clear();
return Response.json('退出成功');
}

退出登录我们只要清理一下跟该客户端的sessions就可以退出了

ok,今天的内容就到这里,我们明天见!

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