注册登录案例

客户端 UI 实现

包含五个页面

  • 闪屏页
  • 登录页
  • 内容主页
    • 设置页
    • 主页
    • 发现页

使用Form控件实现表单提交,并处理返回键拦截。

服务端实现

原理

理解两个概念

  • Authentication:用户认证,一般是通过用户名密码来确认用户是否为系统中合法主体
  • Authorization:用户授权,一般是给系统中合法主体授予相关资源访问权限

OAuth 2.0

OAuth2是一个关于授权的开放标准,核心思路是通过各类认证手段(具体什么手段OAuth2不关心)认证用户身份,并颁发token(令牌),使得第三方应用可以使用该token(令牌)在限定时间、限定范围访问指定资源。

OAuth2 文档

OAuth2 RFC6749文档

关于OAuth2.0 的中文解释,可以阅读这篇博客 理解OAuth 2.0

这里主要包含四个角色

  • Client:第三方应用,获取资源服务器提供的资源
  • Resource Owner:拥有被访问资源的用户
  • Authorization Server:授权服务器,提供授权许可code、令牌token等
  • Resource Server:资源服务器,拥有被访问资源的服务器,需要通过token来确定是否有权限访问

在较小的业务实现中,资源服务器和认证服务器是一个服务器,但是较大规模的部署中通常将其构建为单独的组件。

OAuth 2.0 规定了四种授权方式

  • 授权码(authorization-code)
  • 隐藏式(implicit)
  • 密码式(password):
  • 客户端凭证(client credentials)

其中授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌,这种方式是最常用的授权方式。各大应用内的QQ,微信,微博登录等是使用的这种方式。

本案例使用的是密码式。如果你高度信任某个应用,也允许把用户名和密码直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为密码式(password)。

JWT机制及其与OAuth 2.0的区别

JWT全称为Json Web Token,号称新一代的认证技术。OAuth2中使用token验证用户登录合法性,但token最大的问题是不携带用户信息,资源服务器无法在本地进行验证,每次对于资源的访问,资源服务器都需要向认证服务器发起请求。普通的OAuth2颁发的就是一串随机hash字符串,本身无意义,而JWT使用一种特殊格式的token,token是有特定含义的,分为三部分:Header、Payload和Signature。这三部分均用base64进行编码,并使用.进行分隔。一个典型的JWT格式的token类似xxxxx.yyyyy.zzzzz

简单说,JWT是基于token的认证协议的实现,而OAuth2是一种授权框架,提供了一套详细的授权协议标准。JWT通常适合一次性的身份认证、API的鉴权等场景,这些场景能充分发挥JWT无状态以及分布式验证的优势。当然,OAuth 2.0也可以和JWT结合起来使用。

JWT RFC 文档

案例实现

只需要明确,当用户使用用户名和密码进行登录时,服务端会返回访问令牌access_token刷新令牌refreshToken访问令牌过期时间给客户端,客户端把令牌保存下来,下次访问服务器只需带上访问令牌证明已经登录,当令牌过期时,我们需要使用刷新令牌,请求新的访问令牌即可

环境准备

检查aqueduct框架的版本

pub global run aqueduct  --version

去官网查看版本号,并更新版本

pub upgrade
pub global activate aqueduct 3.3.0+1

可以使用如下命令查看模板,并创建支持auth的模板

# 查看支持的模板
pub global run aqueduct create list-templates
# -t 指定模板,并创建名为login_service的工程
pub global run aqueduct create -t db_and_auth login_service

进入工程,修改config.yaml文件,配置数据库(提前创建好指定的数据库dart_db)

database:
 username: postgres
 password: '123456'
 host: localhost
 port: 5432
 databaseName: dart_db

生成相应表,执行数据库迁移(详情查看 aqueduct 中文文档

pub global run aqueduct db generate

注意,执行迁移时有两种方式

  • 命令行指定(需在命令行中指定数据库的用户名、密码、端口等信息)

    pub global run aqueduct db upgrade --connect postgres://username:password@localhost:5432/my_application

  • 配置文件指定(推荐)

    在项目根路径下创建配置文件database.yaml,添加配置项。需注意,这里与config.yaml配置文件的结构是不同的。

    username: postgres
    password: '123456'
    host: localhost
    port: 5432
    databaseName: dart_db
    

    然后执行命令pub global run aqueduct db upgrade

用户模型定义

打开工程下model/user.dart文件,我们可以修改用户的定义,增加更多字段

如下示例

class User extends ManagedObject<_User>
    implements _User, ManagedAuthResourceOwner<_User> {
  @Serialize(input: true, output: false)
  String password;
}

class _User extends ResourceOwnerTableDefinition {
  // 用户昵称
  @Column(nullable: true)
  String nickName; 

  // 头像
  @Column(nullable: true)
  String avatar; 

  // 创建时间
  DateTime createTime; 
}

生成API文档

可查看中文文档

执行命令生成 Swagger 规范

pub global run aqueduct document > swagger.json

打开 swagger 工具 ,导入生成的json文件,可视化查看接口

设置客户端标识符

文档

pub global run aqueduct auth add-client --id com.arcticfox.flutterregisterlogin

启动服务器

pub global run aqueduct serve

验证码处理

使用Dart 的 image库 生成验证码图像。

修改路由,添加验证码获取接口。

常见的媒体格式类型如下:

  • text/html : HTML格式
  • text/plain :纯文本格式
  • text/xml : XML格式
  • image/gif :gif图片格式
  • image/jpeg :jpg图片格式
  • image/png:png图片格式

状态码文档

总结

  1. 通常使用HTTPS协议,解决传输过程中Token被截获的安全问题。在Dart服务器之前部署反向代理服务器,推荐使用Nginx。

  2. 移动端的验证码方案应考虑手机短信验证

  3. 客户端和服务端都应该做验证码校验,防止爬虫绕过客户端发起请求。

  4. aqueduct框架默认创建的access_token有效期为24小时,可以在AuthController中修改有效时间

          if (grantType == "password") {
            final token = await authServer.authenticate(
                username, password, basicRecord.username, basicRecord.password,
                requestedScopes: scopes);
    
            return AuthController.tokenResponse(token);
          }
    
    ///   设置 authenticate 方法中的 expiration 参数
    ///   Future<AuthToken> authenticate(
    ///       String username, String password, String clientID, String clientSecret,
    ///       {Duration expiration = const Duration(hours: 24),
    ///       List<AuthScope> requestedScopes})
    

公众号“编程之路从0到1”

20190301102949549

Copyright © Arcticfox 2020 all right reserved,powered by Gitbook文档修订于: 2022-05-01 12:00:54

results matching ""

    No results matching ""