API接口JWT方式的Token认证(下),客户端(Android)的实现

上篇文章已经介绍了 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"
        
  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
首先,我们需要安装 `Microsoft.AspNet.WebApi` 和 `Microsoft.Owin.Security.Jwt` NuGet 包。 接下来,我们需要在 `WebApiConfig.cs` 文件中配置 Web API 路由: ```csharp public static void Register(HttpConfiguration config) { // 配置路由 config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); // 配置 JWT 认证 ConfigureJwtAuth(config); } ``` 然后,我们需要在 `Web.config` 文件中配置 JWT 令牌的密钥和有效期: ```xml <appSettings> <add key="jwtSecret" value="my_secret_key" /> <add key="jwtExpireDays" value="7" /> </appSettings> ``` 接下来,我们需要创建一个 `JwtAuthManager` 类来管理 JWT 认证: ```csharp using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; using System.Text; using Microsoft.IdentityModel.Tokens; public class JwtAuthManager : IJwtAuthManager { private readonly string _jwtSecret; private readonly double _jwtExpireDays; public JwtAuthManager(string jwtSecret, double jwtExpireDays) { _jwtSecret = jwtSecret; _jwtExpireDays = jwtExpireDays; } public string GenerateToken(IEnumerable<Claim> claims) { var key = Encoding.ASCII.GetBytes(_jwtSecret); var jwtToken = new JwtSecurityToken( claims: claims, expires: DateTime.Now.AddDays(_jwtExpireDays), signingCredentials: new SigningCredentials( new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) ); var token = new JwtSecurityTokenHandler().WriteToken(jwtToken); return token; } } ``` 然后,我们需要创建一个 `JwtAuthAttribute` 特性,用于在控制器或操作方法上应用 JWT 认证: ```csharp [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class JwtAuthAttribute : AuthorizeAttribute { public override void OnAuthorization(HttpActionContext actionContext) { try { var token = actionContext.Request.Headers.Authorization.Parameter; var jwtAuthManager = actionContext.ControllerContext.Configuration .DependencyResolver.GetService(typeof(IJwtAuthManager)) as IJwtAuthManager; var principal = jwtAuthManager.ValidateToken(token); Thread.CurrentPrincipal = principal; HttpContext.Current.User = principal; } catch (Exception) { actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized); return; } base.OnAuthorization(actionContext); } } ``` 最后,我们需要在 `ConfigureJwtAuth` 方法中注册依赖项并配置 JWT 认证: ```csharp private static void ConfigureJwtAuth(HttpConfiguration config) { var jwtSecret = ConfigurationManager.AppSettings["jwtSecret"]; var jwtExpireDays = double.Parse(ConfigurationManager.AppSettings["jwtExpireDays"]); var container = new UnityContainer(); container.RegisterType<IJwtAuthManager, JwtAuthManager>( new InjectionConstructor(jwtSecret, jwtExpireDays)); config.DependencyResolver = new UnityResolver(container); config.Filters.Add(new JwtAuthAttribute()); } ``` 现在,我们可以在控制器或操作方法上应用 `JwtAuth` 特性来启用 JWT 认证: ```csharp [RoutePrefix("api/products")] public class ProductsController : ApiController { [HttpGet] [Route("")] [JwtAuth] public IHttpActionResult Get() { // ... } [HttpGet] [Route("{id}")] [JwtAuth] public IHttpActionResult Get(int id) { // ... } [HttpPost] [Route("")] [JwtAuth] public IHttpActionResult Post([FromBody] Product product) { // ... } // ... } ``` 这样,我们就成功地基于 JWT 实现Token 签名认证

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值