如何在Http请求中使用Cookie传递用户token,实现登录状态保持?

648 篇文章 6 订阅
1 篇文章 0 订阅

前言

OpenHarmony 作为万物互联的操作系统,网络连接是最基础的能力。其中,有大量的网络应用需要进行用户认证,那么在 OpenHarmony 的应用开发中,用户登录后,如何在 Http 请求中使用 Cookie 传递用户 token,实现登录状态保持?

需求

在 OpenHarmony 中使用@ohos.net.http模块实现网络请求,我们需要实现网络应用用户登录及登录状态保持,但在接口介绍文档、Sample 中并未提供如何保存及使用 Cookie 的示例。

实现

那么下面就通过一个网络音乐应用的例子(应用详细介绍链接在文末),为大家介绍如何实现用户 Token 传递,服务器使用 Django 框架提供的 django.contrib.auth 模块实现用户登录鉴权。

1、用户登录

服务端:

获取 csrf_token 接口:

def get_csrf_token(request):
    csrf_token = get_token(request)
    return JsonResponse({'csrf_token': csrf_token})

登录接口:


def login_request(request):
    username = request.POST.get('username')
    password = request.POST.get('password')
    print('login from app')
    print(request.POST)
    # 使用authenticate函数来认证用户
    user = authenticate(request, username=username, password=password)
  
    if user is not None:
        # 用户认证成功,使用login函数来记录登录状态
        login(request, user)
  
        # 设置一个欢迎信息,可以将其改为HttpResponse或重定向
        return JsonResponse({'res':"login success!"})
    else:
        # 认证失败,返回错误信息
        return JsonResponse({'res':"login failed!"})

应用端:

先获取服务器 CSRF token,然后使用用户名密码登录。

login() {
    try {
      this.httpRequest.request(ServerConstants.CSRF_URL,
        (err: Error, data: http.HttpResponse) => {
          if (!err) {
            console.info('HttpResponse Result:' + data.result);
            const jsonObject: object = JSON.parse(data.result as string);
            this.csrfToken = jsonObject['csrf_token'];
            this.httpRequest.request(ServerConstants.LOGIN_URL,
              {
                method: http.RequestMethod.POST,
                extraData: 'username=' + this.userName + '&password=' + this.password,
                header: {
                  'content-Type': 'application/x-www-form-urlencoded',
                  'X-CSRFToken': this.csrfToken,
                  'Cookie': 'csrftoken=' + this.csrfToken + ';'
                },
              },
              (err: Error, data: http.HttpResponse) => {
                if (!err) {
                  console.info('HttpResponse Result:' + data.result);
                  console.info('HttpResponse code:' + data.responseCode);
                  if (200 === data.responseCode) {
                    this.loginInfo = this.userName
                    this.loginCookie = data.header['set-cookie'];
                  }
                  console.info('HttpResponse type:' + JSON.stringify(data.resultType));
                  console.info('HttpResponse header:' + JSON.stringify(data.header));

                  this.getCustomListFromServer();
                } else {
                  console.info('HttpResponse error:' + JSON.stringify(err));
                }
              });
          } else {
            console.info('HttpResponse error:' + JSON.stringify(err));
          }
        });
    } catch (err) {
      console.info('HttpRequest error:' + JSON.stringify(err));
    }
  }

登录成功后将 Cookie 保存:this.loginCookie = data.header['set-cookie'];

Cookie 内容如下:

  • ["csrftoken=VPfo0sQoTzgsRhSrySJsoQZQMxwZWqmAm0Y4L1szUdbwOv41M19tkprs73w6pNrH; expires=Thu, 12 Jun 2025 09:20:42 GMT; Max-Age=31449600; Path=/; SameSite=Lax", "sessionid=e45smklhb4gdaimk3c3pm0kpv1c7u3lq; expires=Thu, 27 Jun 2024 09:20:42 GMT; HttpOnly; Max-Age=1209600; Path=/; SameSite=Lax" ]

2、后续请求

服务端:

根据用户查询信息的接口:

def get_playlists(request):
    print(request.user)
    playlists = Playlist.objects.filter(user=request.user).values('playlist_name','song').distinct()
    result = []
    for playlist in playlists:
        song = Song.objects.filter(id=playlist.get('song')).values('id', 'name', 'singer','language').first()
        combined_queryset = playlist | song
        result.append(combined_queryset)
    return JsonResponse(result, safe=False)

应用端:

使用保存的 Cookie,放在请求头中,服务端即能从 request 中获取用户信息。

需要根据请求 Cookie 进行格式转换:

this.loginCookie.map(cookie => {
              const parts = cookie.split('=');
              return `${parts[0]}=${parts[1]}`;
            }).join('; ')

完整接口:

getCustomListFromServer() {
    this.customPlayLists = [];
    try {
      this.httpRequest.request(ServerConstants.CUSTOM_LIST_URL,
        {
          method: http.RequestMethod.GET,
          header: {
            'Cookie': this.loginCookie.map(cookie => {
              const parts = cookie.split('=');
              return `${parts[0]}=${parts[1]}`;
            }).join('; ')
          }
        },
        (err: Error, data: http.HttpResponse) => {
          if (!err) {
            console.info('HttpResponse getCustomListFromServer Result:' + data.result);
            interface PlaylistItem {
              playlist_name: string;
              song: number;
              id: number;
              name: string;
              singer: string;
              language: string;
            }
            let jsonObject: PlaylistItem[]  = JSON.parse(data.result as string);
            let groupedByPlaylistName = jsonObject.reduce((accumulator, item) => {
              if (!accumulator[item.playlist_name]) {
                accumulator[item.playlist_name] = [];
              }
              accumulator[item.playlist_name].push(item);
              return accumulator;
            }, {} as  Record<string, PlaylistItem[]>);
            const keys = Object.keys(groupedByPlaylistName);
            keys.forEach((playlistName) => {
              console.log(`Playlist: ${playlistName}`);
              let aPlayingList: AudioItem[] = Array<AudioItem>();
              groupedByPlaylistName[playlistName].forEach((song, index) => {
                aPlayingList.push(new AudioItem(song.name, song.singer, song.id.toString()));
              });
              this.customPlayLists.push(new PlayListData(playlistName, $r('app.media.icon'), aPlayingList.length + '首',
                aPlayingList, ''));
            });
          } else {
            console.info('HttpResponse error:' + JSON.stringify(err));
          }
        });
    } catch (err) {
      console.info('HttpRequest error:' + JSON.stringify(err));
    }
  }

遗留问题

在开发过程中,参考接口文档时,http 模块提供了一个缓存接口:

按说明理解,应该可以实现自动缓存 cookie 的功能,但是按示例代码尝试后并不生效,不知和本文所需要的功能是否相同,或者说有 bug,有待大家探索。

  • 24
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值