Javascript 反应本机+;Redux基本身份验证

Javascript 反应本机+;Redux基本身份验证,javascript,authentication,react-native,redux,Javascript,Authentication,React Native,Redux,我正在寻找一种为我的react本机应用程序创建基本身份验证的方法。 我找不到任何关于react原生应用程序的好例子 要登录,应用程序会将电子邮件/密码+clientSecret发送到我的服务器 如果确定,服务器将返回accessToken+refreshToken 用户登录后,所有其他请求都包括带有accessToken的承载者 如果accessToken过期,应用程序会自动使用refreshToken请求一个新的 用户始终保持登录状态,状态应保存在手机中 最好的方法是什么 谢谢。我在这方面

我正在寻找一种为我的react本机应用程序创建基本身份验证的方法。 我找不到任何关于react原生应用程序的好例子

  • 要登录,应用程序会将电子邮件/密码+clientSecret发送到我的服务器
  • 如果确定,服务器将返回accessToken+refreshToken
  • 用户登录后,所有其他请求都包括带有accessToken的承载者
  • 如果accessToken过期,应用程序会自动使用refreshToken请求一个新的
  • 用户始终保持登录状态,状态应保存在手机中
最好的方法是什么


谢谢。

我在这方面没有看到太多的例子,我认为这肯定需要更多的报道。我自己还没有实现auth,否则我会向您介绍一些代码示例。但我可以给你指出我收集的几个链接,它们可能会帮助你朝着正确的方向发展


无论您如何执行身份验证,都需要安全地存储访问、刷新和秘密令牌。在iOS上,我相信你会使用Android来实现这一点,而对于Android来说,这似乎就是最好的方式。您可能会发现它很有用,尽管它还不支持android it

当应用程序与实施某种形式的身份验证的HTTP API通信时,应用程序通常遵循以下步骤:

  • 应用程序未经过身份验证,因此我们会提示用户登录
  • 用户输入其凭据(用户名和密码),然后点击提交
  • 我们将这些凭据发送到API,并检查响应:
    • 成功时(200-OK):我们缓存身份验证令牌/哈希,因为我们将在每个后续请求中使用此令牌/哈希。
      • 如果令牌/哈希在任何后续API请求(401-未经授权)期间不起作用,我们需要使哈希/令牌无效,并提示用户再次登录
    • 或者,失败时(401-未授权):我们向用户显示一条错误消息,提示他们重新输入凭据
  • 登录 根据上面定义的工作流程,我们的应用程序从显示登录表单开始,当用户点击登录按钮时,第2步开始,该按钮将发送下面的
    登录
    操作创建者:

    /// actions/user.js
    
    export function login(username, password) {
      return (dispatch) => {
    
        // We use this to update the store state of `isLoggingIn`          
        // which can be used to display an activity indicator on the login
        // view.
        dispatch(loginRequest())
    
        // Note: This base64 encode method only works in NodeJS, so use an
        // implementation that works for your platform:
        // `base64-js` for React Native,
        // `btoa()` for browsers, etc...
        const hash = new Buffer(`${username}:${password}`).toString('base64')
        return fetch('https://httpbin.org/basic-auth/admin/secret', {
          headers: {
            'Authorization': `Basic ${hash}`
          }
        })
        .then(response => response.json().then(json => ({ json, response })))
        .then(({json, response}) => {
          if (response.ok === false) {
            return Promise.reject(json)
          }
          return json
        })
        .then(
          data => {
            // data = { authenticated: true, user: 'admin' }
            // We pass the `authentication hash` down to the reducer so that it
            // can be used in subsequent API requests.
    
            dispatch(loginSuccess(hash, data.user))
          },
          (data) => dispatch(loginFailure(data.error || 'Log in failed'))
        )
      }
    }
    
    上面的函数中有很多代码,但请放心 大部分代码都在清理响应,并且可以被抽象掉

    我们要做的第一件事是发送一个操作
    LOGIN\u请求
    ,它更新我们的存储并让我们知道用户
    正在登录

    dispatch(loginRequest())
    
    我们使用它来显示一个活动指示器(旋转的轮子,“加载…”等),并在我们的登录视图中禁用登录按钮

    接下来,我们为http basic auth对用户的用户名和密码进行base64编码,并将其传递给请求的头

    const hash = new Buffer(`${username}:${password}`).toString('base64')
    return fetch('https://httpbin.org/basic-auth/admin/secret', {
      headers: {
        'Authorization': `Basic ${hash}`
      }
    /* ... */
    
    如果一切顺利,我们将发送一个
    LOGIN\u SUCCESS
    操作,这将导致我们的存储中有一个身份验证
    hash
    ,我们将在后续请求中使用它

    dispatch(loginSuccess(hash, data.user))
    
    另一方面,如果出现问题,我们还想让用户知道:

    dispatch(loginFailure(data.error || 'Log in failed')
    
    loginsucess
    loginFailure
    loginRequest
    操作创建者相当通用,并不真正保证代码示例。见:

    减速器 我们的减速器也是典型的:

    /// reducers/user.js
    function user(state = {
      isLoggingIn: false,
      isAuthenticated: false
    }, action) {
      switch(action.type) {
        case LOGIN_REQUEST:
          return {
            isLoggingIn: true, // Show a loading indicator.
            isAuthenticated: false
          }
        case LOGIN_FAILURE:
          return {
            isLoggingIn: false,
            isAuthenticated: false,
            error: action.error
          }
        case LOGIN_SUCCESS:
          return {
            isLoggingIn: false,
            isAuthenticated: true, // Dismiss the login view.
            hash: action.hash, // Used in subsequent API requests.
            user: action.user
          }
        default:
          return state
      }
    }
    
    后续API请求 现在我们的存储中有了一个身份验证哈希,我们可以将它传递到后续请求的头中

    const hash = new Buffer(`${username}:${password}`).toString('base64')
    return fetch('https://httpbin.org/basic-auth/admin/secret', {
      headers: {
        'Authorization': `Basic ${hash}`
      }
    /* ... */
    
    在下面的示例中,我们为经过身份验证的用户获取朋友列表:

    /// actions/friends.js
    export function fetchFriends() {
      return (dispatch, getState) => {
    
        dispatch(friendsRequest())
    
        // Notice how we grab the hash from the store:
        const hash = getState().user.hash
        return fetch(`https://httpbin.org/get/friends/`, {
          headers: {
            'Authorization': `Basic ${hash}`
          }
        })
        .then(response => response.json().then(json => ({ json, response })))
        .then(({json, response}) => {
          if (response.ok === false) {
            return Promise.reject({response, json})
          }
          return json
        })
        .then(
          data => {
            // data = { friends: [ {}, {}, ... ] }
            dispatch(friendsSuccess(data.friends))
          },
          ({response, data}) => {
            dispatch(friendsFailure(data.error))
    
            // did our request fail because our auth credentials aren't working?
            if (response.status == 401) {
              dispatch(loginFailure(data.error))
            }
          }
        )
      }
    }
    
    您可能会发现,大多数API请求通常会发送与上面相同的3个操作:
    API\u请求
    API\u成功
    、和
    API\u失败
    ,因此大部分请求/响应代码都可以推送到Redux中间件中

    我们从存储中获取哈希身份验证令牌并设置请求

    const hash = getState().user.hash
    return fetch(`https://httpbin.org/get/friends/`, {
      headers: {
        'Authorization': `Basic ${hash}`
      }
    })
    /* ... */
    
    如果API响应带有401状态代码,那么我们必须从存储中删除哈希,并再次向用户提供登录视图

    if (response.status == 401) {
      dispatch(loginFailure(data.error))
    }
    

    我一般地回答了这个问题,并且只处理http基本身份验证

    我认为这个概念可能保持不变,您将在存储中推送
    accessToken
    refreshttoken
    ,并在后续请求中提取它

    dispatch(loginSuccess(hash, data.user))
    

    如果请求失败,那么您必须发送另一个操作来更新accessToken,然后重新调用原始请求。

    我正在制作一个视频教程系列,其中至少回答了您提出的一些问题。视频以及成绩单和示例代码可在此处找到:

    无法为您编写完整的示例,但请查看您在客户端和服务器之间传递的内容。这将允许您执行DB-less角色和您想要的过期行为。我将用一个完整的示例来完成我正在处理的repo。(向上投票)@peterp这是基本身份验证的一个很好的示例,但是您对“记住我”功能中的持久性有何想法?我见过的大多数应用只需要在首次发布时获得您的凭据,而不是每次发布时,除非它们与财务相关(或类似),我还有一个问题。您会建议创建一个中间件来注入承载器吗?@ChrisGeirman我认为您建议将身份验证令牌存储在安全的东西中,如keychain(iOS)和keystore(Android)可能是最好的。@alexmngn是的,我会的,实际上我自己也在忙着这么做,“如何简化样板文件”redux文档中的一节对此进行了相当好的讨论。react native keychain现在支持在Android中搜索“最后,您可以编写自己的中间件了!”!掌声@obladorHey@oblador和Chris,我想使用keychain在两个不同的本地应用程序之间共享pass或任何字符串。我有麻烦了,你有什么建议吗?我也有这个问题张贴。谢谢你