上篇文章已经介绍了 JWT 认证在 Laravel 框架服务器上的实现。这篇文章继续介绍 Android 客户端的实现。回顾下 JWT 认证的流程,客户端先提交账号密码进行登录,账号密码验证成功后,服务器会生成一个 token,其中包含了用户信息,token 到期时间等信息,服务器将 token 返回给客户端后不会保存此 token。客户端接受到 token 后,需要对 token进行存储,在以后访问需要认证的 API 接口是,在 HTTP 请求通过认证头提交 token,服务器校验 token 的合法性,是否过期,携带的用户信息是否匹配,全部通过后,完成验证,之后才能完成后续操作。
先看一下已经实现的 API 接口的路由:
$api = app('Dingo\Api\Routing\Router');
$api->version('v1', ['namespace' => 'App\Http\Controllers'], function ($api) {
$api->get('login', 'Auth\AuthenticateController@authenticate');
$api->post('register', 'Auth\RegisterController@register');
$api->group(['middleware' => 'jwt.auth', 'providers' => 'jwt'], function ($api) {
$api->get('user', 'UserController@getUserInfo');
$api->get('notices', 'NoticeController@index');
});
});
其中 login 和 register 是用来获取 token 的,而 user 和 notices 则需要客户端提供 token 。下面我们就在 Android 客户端上实现对这些接口的访问。
我们继续在 Jokes 项目上进行开发,Jokes 采用 MVP + Retrofit + RxJava 的架构,具体细节可以参考我之前的两篇文章:
使用MVP+Retrofit+RxJava实现的的Android Demo (上)使用Nuclues库实现MVP
使用MVP+Retrofit+RxJava实现的的Android Demo (下)使用Retrofit+RxJava处理网络请求
本文采用的 Android 代码下载地址:
https://github.com/zhongchenyu/jokes
由于后续可能会重构代码,本文使用的代码保存在 demo2 分支。
1.构建 UI
在主页新增一页 MoreFragment,布局文件代码如下:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_height="match_parent"
tools:context="chenyu.jokes.feature.more.MoreFragment" android:orientation="vertical"
android:background="@color/bgGrey">
<RelativeLayout
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:background="@android:color/white">
<ImageView android:id="@+id/avatar"
android:layout_width="80dp" android:layout_height="80dp"
android:layout_alignParentStart="true" app:srcCompat="@drawable/ic_36"
android:layout_marginStart="16dp" android:layout_marginTop="16dp"
android:layout_centerVertical="true" android:adjustViewBounds="false"/>
<TextView android:id="@+id/name"
android:layout_width="wrap_content" android:layout_height="32dp"
android:visibility="invisible" android:textSize="24sp"
android:layout_toEndOf="@+id/avatar" android:layout_marginStart="16dp"
android:layout_alignParentTop="true" android:layout_marginTop="8dp"/>
<TextView android:id="@+id/email"
android:layout_width="wrap_content" android:layout_height="32dp"
android:textSize="16sp" android:visibility="invisible"
android:layout_toEndOf="@+id/avatar" android:layout_marginStart="16dp"
android:layout_marginTop="8dp" android:layout_below="@+id/name"/>
<Button android:id="@+id/login"
android:text="登录"
android:layout_width="72dp" android:layout_height="32dp"
android:layout_toEndOf="@+id/avatar" android:layout_centerVertical="true"
android:layout_marginStart="32dp" android:padding="0dp"
android:textColor="@android:color/white" android:textSize="16sp"
android:background="@drawable/selector_bg_corner"/>
<Button android:id="@+id/register"
android:text="注册" android:padding="0dp"
android:layout_width="72dp" android:layout_height="32dp"
android:background="@drawable/selector_bg_corner" android:layout_toEndOf="@+id/login"
android:textColor="@android:color/white" android:textSize="16sp"
android:layout_centerVertical="true" android:layout_marginStart="16dp"/>
<Button android:id="@+id/logout"