【问题标题】:setting permissions on redux actions设置 redux 操作的权限
【发布时间】:2016-05-18 03:39:09
【问题描述】:

我正在创建一个 web redux-react 应用程序,该应用程序将具有许多不同的权限级别。许多用户可能正在与一个数据进行交互,但有些用户可能会限制他们可以做什么。

对我来说,设置数据交互权限的明显方法(保存在应用服务器后面)是将某些权限与不同的 redux 操作相关联。然后,当用户保存他们的状态时,客户端应用程序将捆绑用户的操作历史并将其发送回服务器。然后可以将这些操作应用于服务器中的数据,并且可以针对用户 jwt 逐个检查权限。

这意味着我们的 reducer 代码可以在服务器上同构地使用很多。

我找不到任何关于此的资源/讨论。在 redux 应用程序中处理复杂权限的正常方法是什么?纯粹在端点进行身份验证似乎很麻烦,这需要重写大量已经在客户端减速器中编写的新代码。有什么理由不继续创建一个 reducer 来检查每个操作的身份验证吗?

积分:

  • 我们必须假设发送到服务器的操作是经过身份验证的,但由无权发送这些操作的用户发送
  • 如果权限已被检查并且在操作中,那么 reducer 可以检查权限并且是纯的

【问题讨论】:

  • 最重要的是,您需要禁止后端的操作,对吗?否则,无论您在前端做什么,您的应用程序都不会安全。之后,为了引导用户了解可以做什么和不可以做什么,您只需隐藏/禁用您的 UI 元素。真的有必要控制动作吗?
  • 没错,问题是,在后端,在用户通过身份验证并对其权限进行双重检查之后,确定是否允许操作的最佳方法是什么。存储中间件?在减速机中?
  • 你在后台运行什么? Node + Redux??
  • 是的,节点。在我提出的用例中,我们也将使用 redux(主要使用一些 reducer 作为前端)。流程是:动作被分派到前端的reducer;经过一堆交互后,用户将点击保存;用户的操作历史被发送到服务器;服务器将操作重新应用到服务器上的状态,并附加权限,这些操作已由 auth 中间件检查;一旦完成,状态将被持久化到一个 db..

标签: authentication reactjs permissions redux


【解决方案1】:

我认为检查权限不是动作创建者的责任,但使用 reducer 和选择器绝对是要走的路。这是一种可能的实现方式。

以下组件需要一些 ACL 检查:

/**
 * Display a user record.
 * 
 * A deletion link is added if the logged user has sufficient permissions to
 * delete the record.
 */
function UserRecord({ username, email, avatar, isGranted, deleteUser }) {
  return (
    <div>
      <img src={avatar} />
      <b>{username}</b>
      {isGranted("DELETE_USER")
        ? <button onClick={deleteUser}>{"Delete"}</button>
        : null
      }
    </div>
  )
}

我们需要将它连接到我们的商店以正确地为所有道具补水:

export default connect(
  (state) => ({
    isGranted: (perm) => state.loggedUser.permissions.has(perm),
  }),
  {deleteUser},
  (stateProps, dispatchProps, ownProps) => ({
    ...stateProps,
    ...ownProps,
    deleteUser: () => dispatchProps.deleteUser(ownProps.user)
  })
)(UserRecord)
  • connect 的第一个参数将为登录用户创建isGranted。这部分可以使用reselect 来提高性能。

  • 第二个参数将绑定动作。这里没什么特别的。

  • 第三个参数将合并所有道具并将它们传递给被包装的组件。 deleteUser 绑定到当前记录。

您现在可以使用 UserRecord 而无需处理 ACL 检查,因为它会根据 loggedUser 中存储的内容自动更新。

<UserRecord user={someUser} />

为了获得上面的示例工作,您需要将登录的用户存储在 Redux 的存储中为loggedUser。您不需要检查操作的 ACL,因为如果当前用户缺乏权限,UI 不会触发它们。此外,必须在服务器端检查 ACL。

【讨论】:

  • 嗨,我不确定我是否完全理解。是的,所有真正的身份验证都需要在服务器端进行。我同意检查我的操作是减速器的工作,而不是动作创建者的工作。如果用户保存,客户端会向服务器发送一大堆操作,然后可以将这些操作发送到服务器上的减速器。我们在什么时候以及如何检查发送的操作是真实的(即,逐个操作,我们应该在什么时候确保用户具有执行每个操作的正确权限)。
【解决方案2】:

您可以设置一个辅助函数,该函数将内置到用于检查用户权限(本地或远程)的操作中,您还可以在错误时提供回调操作创建器。当然需要redux-thunk 或类似名称,以便您可以从其他操作中分派操作。

您应该在这里遵守的关键规则是:

reducer 是纯函数。

动作创建者可能不纯。这意味着在给定相同参数的情况下,reducers 总是返回相同的值。在 reducer 中检查 ACL 权限将违反该规则。

假设您需要获取联系人列表。您的操作是REQUEST_CONTACTS。动作创建者首先会派发类似的东西:

// ACL test function
function canAccessContacts(dispatch) {
    if (user !== 'cool') {
        dispatch({type: 'ACCESS_DENIED'});
        return false;
    }
}

// Action creator
function fetchContacts() {
    return (dispatch) => {
        if (!canAccessContacts(dispatch)) {
            return false;
        }

        // your logic for retrieving contacts goes here
        dispatch({
            type: 'RECEIVE_CONTACTS',
            data: your_contacts_data_here
        });
      };
}

RECEIVE_CONTACTS 将在您返回数据后被触发。 REQUEST_CONTACTS 和 RECEIVE_CONTACTS(可能是异步调用)之间的时间是显示加载指示器的机会。

当然,这是一个非常原始的例子,但它应该能让你继续前进。

【讨论】:

  • 如果操作是在客户端创建的,这个解决方案是否仍然有效?我想将 auth+permissions 附加到操作返回服务器时,然后一旦操作到达 reducer 检查权限..
  • @Eoin 是的,您可以异步检查权限。请注意,reducer 不应该检查权限,因为它们是纯函数。
  • 如果用户权限附加到操作上,那么reducer 可以检查权限并且是纯的。即 (state, {actionData, badPermision}) => state, (state, {actionData, goodPermision}) => newState
猜你喜欢
  • 2017-01-24
  • 2012-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-06
  • 2017-07-12
相关资源
最近更新 更多