[英]React Native + Redux basic authentication
I'm looking for a way to create a basic authentication for my react-native app. 我正在寻找一种为我的react-native应用程序创建基本身份验证的方法。 I couldn't find any good example for react-native app. 我找不到react-native app的任何好例子。
What would be the best approach for this? 对此最好的方法是什么?
Thanks. 谢谢。
When an app communicates with a HTTP API which enforces some form of authentication, the app typically follows these steps: 当应用程序与强制执行某种形式身份验证的HTTP API进行通信时,应用程序通常会遵循以下步骤:
Based on the work flow defined above our app starts by displaying a login form, step 2 kicks in when the user taps the login button which dispatches the login
action creator below: 根据上面定义的工作流程,我们的应用程序首先显示一个登录表单,当用户点击下面的login
操作创建者的登录按钮时, 第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'))
)
}
}
There's a lot of code in the function above, but take comfort in the fact that the majority of the code is sanitising the response and can be abstracted away. 上面的函数中有很多代码,但是大多数代码都在清理响应并且可以将其抽象出来。
The first thing we do is dispatch an action LOGIN_REQUEST
which updates our store and lets us know that the user isLoggingIn
. 我们要做的第一件事就是调度一个动作LOGIN_REQUEST
来更新我们的商店并让我们知道用户正在isLoggingIn
。
dispatch(loginRequest())
We use this to display an activity indicator ( spinning wheel, "Loading...", etc. ), and to disable the log in button in our log in view. 我们使用它来显示活动指示器( 旋转轮,“正在加载...”等 ),并在我们的登录视图中禁用登录按钮。
Next we base64 encode the user's username and password for http basic auth, and pass it to the request's headers. 接下来,我们base64编码用户的http basic auth的用户名和密码,并将其传递给请求的标头。
const hash = new Buffer(`${username}:${password}`).toString('base64')
return fetch('https://httpbin.org/basic-auth/admin/secret', {
headers: {
'Authorization': `Basic ${hash}`
}
/* ... */
If everything went well, we'll dispatch a LOGIN_SUCCESS
action, which results in us having an authentication hash
in our store, which we'll use in subsequent requests. 如果一切顺利,我们将调度一个LOGIN_SUCCESS
操作,这会导致我们在商店中有一个身份验证hash
,我们将在后续请求中使用。
dispatch(loginSuccess(hash, data.user))
On the flip side, if something went wrong then we also want to let the user know: 另一方面,如果出现问题,我们也想让用户知道:
dispatch(loginFailure(data.error || 'Log in failed')
The loginSuccess
, loginFailure
, and loginRequest
action creators are fairly generic and don't really warrant code samples. loginSuccess
, loginFailure
和loginRequest
操作创建者是相当通用的,并不真正保证代码示例。 See: https://github.com/peterp/redux-http-basic-auth-example/blob/master/actions/user.js) 请参阅: https : //github.com/peterp/redux-http-basic-auth-example/blob/master/actions/user.js)
Our reducer is also typical: 我们的减速机也很典型:
/// 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
}
}
Now that we have an authentication hash in our store we can pass it into subsequent request's headers. 现在我们在商店中有一个身份验证哈希,我们可以将它传递给后续请求的头文件。
In our example below we're fetching a list of friends for our authenticated user: 在下面的示例中,我们为经过身份验证的用户提取了一个朋友列表:
/// 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))
}
}
)
}
}
You may find that most API requests typically dispatch the same 3 actions as above: API_REQUEST
, API_SUCCESS
, and API_FAILURE
, and as such the majority of the request/ response code can be pushed into Redux middleware. 您可能会发现大多数API请求通常会调度与上述相同的3个操作: API_REQUEST
, API_SUCCESS
和API_FAILURE
,因此大多数请求/响应代码都可以推送到Redux中间件。
We fetch the hash authentication token from the store and setup the request. 我们从商店获取哈希认证令牌并设置请求。
const hash = getState().user.hash
return fetch(`https://httpbin.org/get/friends/`, {
headers: {
'Authorization': `Basic ${hash}`
}
})
/* ... */
If the API response with a 401 status code then we've got to remove our hash from the store, and present the user with a log in view again. 如果API响应带有401状态代码,那么我们必须从商店中删除我们的哈希,并再次向用户显示日志。
if (response.status == 401) {
dispatch(loginFailure(data.error))
}
I've answered the question generically and only dealing with http-basic-auth. 我一般都回答了这个问题,只处理了http-basic-auth。
I think that the concept may remain the same, you'll push the accessToken
and refreshToken
in the store, and extract it in subsequent requests. 我认为概念可能保持不变,您将在商店中推送accessToken
和refreshToken
,并在后续请求中提取它。
If the request fails then you'll have to dispatch another action which updates the accessToken, and then recalls the original request. 如果请求失败,那么您将不得不分派另一个更新accessToken的操作,然后调用原始请求。
I haven't seen too much by way of examples in this area, and think it's definitely something that needs more coverage. 我在这个领域没有看到太多的例子,并且认为它肯定需要更多的报道。 I've not yet implemented auth myself, else I'd point you to some code examples. 我自己还没有实现auth,否则我会指出一些代码示例。 But I can point you to a couple links I've collected that may help you in the right direction... 但我可以向您指出我收集的一些链接,可以帮助您朝着正确的方向......
Regardless how you perform your auth, you'll need to securely store your access, refresh, and secret tokens. 无论您如何执行身份验证,都需要安全地存储访问权限,刷新权限和秘密令牌。 On iOS I believe you'd do that using keychain and for Android it looks like KeyStore is the way. 在iOS上我相信你会使用钥匙串来做到这一点,对于Android来说,它看起来像是KeyStore 。 You may find oblador/react-native-keychain helpful, though it doesn't yet support android it looks like it may support android soon . 你可能会发现oblador / react-native-keychain很有用,虽然它还不支持android它看起来很快就会支持android 。
I'm actually working on a video tutorial series that answers at least some of the questions your asking. 我实际上正在制作一个视频教程系列,至少可以回答你提出的一些问题。 The video along with a transcript and sample code can be found here: http://codecookbook.co/post/how-to-build-a-react-native-login-form-with-redux-pt1/ 视频以及成绩单和示例代码可在此处找到: http : //codecookbook.co/post/how-to-build-a-react-native-login-form-with-redux-pt1/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.