احراز هویت کاربر با React Native Navigation — راهنمای کاربردی

۱۲۲ بازدید
آخرین به‌روزرسانی: ۲۰ شهریور ۱۴۰۲
زمان مطالعه: ۶ دقیقه
احراز هویت کاربر با React Native Navigation — راهنمای کاربردی

در بخش قبلی این مطلب در مورد کتابخانه React Native Navigation صحبت کردیم. در بخش دوم و پایانی این سری مقالات به بررسی روش‌های احراز هویت کاربر به کمک این کتابخانه خواهیم پرداخت. برای مطالعه بخش قبلی به لینک زیر مراجعه کنید:

997696

کار خود را از جایی که در بخش اول باقی مانده بود از سر می‌گیریم و اینک می‌خواهیم با استفاده از AWS یک بخش واقعی ثبت نام و ورود کاربر به اپلیکیشن بسازیم. بدین منظور از AWS Amplify برای اتصال به AWS و از Amazon Cognito برای مدیریت کاربران استفاده می‌کنیم. اگر کد بخش قبلی را نوشته‌اید، می‌توانید شروع به کار روی آن بکنید، اما اگر آن کد را ندارید می‌توانید از این ریپو (+) استفاده کنید.

ایجاد سرویس Auth

از root پروژه ری‌اکت نیتیو آغاز می‌کنیم و یک پروژه جدید AWS را طوری مقداردهی می‌کنیم که بتوانیم احراز هویت را اضافه کنیم.

به این منظور باید AWS Mobile CLI را نصب و پیکربندی کنیم:

npm i -g awsmobile-cli
awsmobile configure

زمانی که CLI را نصب و پیکربندی کردید، یک پروژه جدید AWS را مقداردهی کنید:

awsmobile init

این دستور چند کار به شرح زیر انجام می‌دهد:

  1. یک پروژه جدید Mobile Hub در حساب AWS ما ایجاد می‌کند.
  2. چند وابستگی را به صورت aws-amplify و aws-amplify-react-native درون پروژه نصب می‌کند.
  3. فایل‌های پیکربندی محلی با اسامی awsmobile.js و aws-exports.js اضافه می‌کند که امکان ویرایش محلی پیکربندی از طریق cli و ارسال تغییرات به پروژه Mobile Hub را در کنسول AWS فراهم می‌سازد.

سپس باید یک وابستگی نیتیو به پروژه React Native خود اضافه کنیم:

react-native link amazon-cognito-identity-js

اینک باید بخش ثبت نام کاربر را به پروژه AWS خود اضافه کنیم:

awsmobile user-signin enable

و آن را به کنسول AWS ارسال کنیم:

awsmobile user-signin enable

اکنون باید کارکرد ثبت نام کاربر ما فعال و آماده استفاده باشد. کل پروژه Mobile Hub را می‌توان در حساب AWS با اجرای دستور awsmobile console از خط فرمان مشاهده کرد. همچنین می‌توانید از کنسول Amazon Cognito بازدید کنید تا پیکربندی آن را ببینید.

نوشتن اپلیکیشن ری‌اکت نیتیو

اکنون که سرویس ایجاد شده است، باید اپلیکیشن را به‌روزرسانی کنیم تا از آن استفاده کند. ابتدا باید فایل index.js را به‌روزرسانی کنیم تا از پیکربندی موجود در فایل aws-exports.js استفاده کرده و با AWS Amplify کار کند.

فایل index.js

1// index.js
2import {Navigation} from 'react-native-navigation';
3import {registerScreens} from './src/screens';
4
5import Amplify from 'aws-amplify'
6import config from './aws-exports'
7Amplify.configure(config)
8
9registerScreens();
10
11Navigation.events().registerAppLaunchedListener(() => {
12  Navigation.setRoot({
13    root: {
14      component: {
15        name: 'Initializing'
16      }
17    },
18  });
19});

در فایل فوق کتابخانه Amplify و همچنین پیکربندی AWS را از aws-exports.js ایمپورت می‌کنیم و تابع Amplify.configure را فراخوانی کرده و پیکربندی را ارسال می‌کنیم. بدین ترتیب پروژه ری‌اکت نیتیو راه‌اندازی شده و امکان آغاز فراخوانی سرویس AWS را با استفاده از Amplify از هر کجا درون اپلیکیشن فراهم می‌سازد.

فایل SignUp.js

در فایل SignUp.js تابع signUp را به‌روزرسانی می‌کنیم تا ثبت نام کاربر جدید را مدیریت کرده و یک تابع confirmSignUp جدید برای MFA بسازیم.

1// SignUp.js
2import React, { Fragment } from 'react'
3import {
4  View,
5  Button,
6  TextInput,
7  StyleSheet
8} from 'react-native'
9import {Navigation} from 'react-native-navigation';
10
11import { Auth } from 'aws-amplify'
12
13const initialState = {
14  username: '', password: '', email: '', phone_number: '', authenticationCode: '', showConfirmationForm: false
15}
16
17export default class SignUp extends React.Component {
18  state = initialState
19  onChangeText = (key, val) => {
20    this.setState({ [key]: val })
21  }
22  signUp = async () => {
23    const { username, password, email, phone_number } = this.state
24    try {
25      const success = await Auth.signUp({ username, password, attributes: { email, phone_number }})
26      console.log('user successfully signed up!: ', success)
27      this.setState({ showConfirmationForm: true })
28    } catch (err) {
29      console.log('error signing up: ', err)
30    }
31  }
32  confirmSignUp = async () => {
33    const { username, authenticationCode } = this.state
34    try {
35      await Auth.confirmSignUp(username, authenticationCode)
36      console.log('successully signed up!')
37      alert('User signed up successfully!')
38      this.setState({ ...initialState })
39    } catch (err) {
40      console.log('error confirming signing up: ', err)
41    }
42  }
43  render() {
44    return (
45      <View style={styles.container}>
46        {
47          !this.state.showConfirmationForm && (
48            <Fragment>
49              <TextInput
50                style={styles.input}
51                placeholder='Username'
52                autoCapitalize="none"
53                placeholderTextColor='white'
54                onChangeText={val => this.onChangeText('username', val)}
55              />
56              <TextInput
57                style={styles.input}
58                placeholder='Password'
59                secureTextEntry={true}
60                autoCapitalize="none"
61                placeholderTextColor='white'
62                onChangeText={val => this.onChangeText('password', val)}
63              />
64              <TextInput
65                style={styles.input}
66                placeholder='Email'
67                autoCapitalize="none"
68                placeholderTextColor='white'
69                onChangeText={val => this.onChangeText('email', val)}
70              />
71              <TextInput
72                style={styles.input}
73                placeholder='Phone Number'
74                autoCapitalize="none"
75                placeholderTextColor='white'
76                onChangeText={val => this.onChangeText('phone_number', val)}
77              />
78              <Button
79                title='Sign Up'
80                onPress={this.signUp}
81              />
82            </Fragment>
83          )
84        }
85        {
86          this.state.showConfirmationForm && (
87            <Fragment>
88              <TextInput
89                style={styles.input}
90                placeholder='Authentication code'
91                autoCapitalize="none"
92                placeholderTextColor='white'
93                onChangeText={val => this.onChangeText('authenticationCode', val)}
94              />
95              <Button
96                title='Confirm Sign Up'
97                onPress={this.confirmSignUp}
98              />
99            </Fragment>
100          )
101        }
102      </View>
103    )
104  }
105}
106
107const styles = StyleSheet.create({
108  input: {
109    width: 350,
110    height: 55,
111    backgroundColor: '#42A5F5',
112    margin: 10,
113    padding: 8,
114    color: 'white',
115    borderRadius: 14,
116  },
117  container: {
118    flex: 1,
119    justifyContent: 'center',
120    alignItems: 'center'
121  }
122})

در این فایل SignUp.js  دو فرم ابتدایی داریم که یکی برای ثبت نام کاربر جدید و دیگری برای تأیید ثبت نام با استفاده از MFA است. فرم تأیید ثبت نام به کاربر امکان می‌دهد که کد MFA خود را برای شناسایی این که این کد را دریافت کرده است وارد کند. ما این دو فرم را بر اساس مقدار بولی this.state.showConfirmationForm نمایش داده یا پنهان می‌کنیم که مقدار آن در متدهای کلاس signUp و confirmSignUp تعیین می‌شود.

متدهایی که برای ثبت نام و تأیید ثبت نام از AWS Amplify استفاده می‌کنیم، به ترتیب Auth.signUp و Auth.confirmSignUp نام دارند.

فایل SignIn.js

این فایل برای به‌روزرسانی تابع signIn جهت مدیریت ثبت نام کاربر و ایجاد تابع جدید confirmSignIn برای MFA استفاده می‌شود.

1// SignIn.js
2import React, { Fragment } from 'react'
3import {
4  View,
5  Text,
6  StyleSheet,
7  TextInput,
8  Button
9} from 'react-native'
10
11import { goHome } from './navigation'
12import { Auth } from 'aws-amplify'
13
14export default class SignIn extends React.Component {
15  state = {
16    username: '', password: '', user: {}, authenticationCode: '', showConfirmationForm: false
17  }
18  onChangeText = (key, value) => {
19    this.setState({ [key]: value })
20  }
21  signIn = async () => {
22    const { username, password } = this.state
23    try {
24       const user = await Auth.signIn(username, password)
25       console.log('user successfully signed in!', user)
26       this.setState({ user, showConfirmationForm: true })
27    } catch (err) {
28      console.log('error:', err)
29    }
30  }
31  confirmSignIn = async () => {
32    const { user, authenticationCode } = this.state
33    try {
34       await Auth.confirmSignIn(user, authenticationCode)
35       console.log('user successfully signed in!', user)
36       goHome()
37    } catch (err) {
38      console.log('error:', err)
39    }
40  }
41  render() {
42    return (
43      <View style={styles.container}>
44        {
45          !this.state.showConfirmationForm && (
46            <Fragment>
47              <TextInput
48                style={styles.input}
49                placeholder='Username'
50                autoCapitalize="none"
51                autoCorrect={false}
52                placeholderTextColor='white'
53                onChangeText={val => this.onChangeText('username', val)}
54              />
55              <TextInput
56                style={styles.input}
57                placeholder='Password'
58                autoCapitalize="none"
59                secureTextEntry={true}
60                placeholderTextColor='white'
61                onChangeText={val => this.onChangeText('password', val)}
62              />
63              <Button
64                title='Sign In'
65                onPress={this.signIn}
66              />
67            </Fragment>
68          )
69        }
70        {
71          this.state.showConfirmationForm && (
72            <Fragment>
73              <TextInput
74                style={styles.input}
75                placeholder='Authentication Code'
76                autoCapitalize="none"
77                placeholderTextColor='white'
78                onChangeText={val => this.onChangeText('authenticationCode', val)}
79              />
80              <Button
81                title='Confirm Sign In'
82                onPress={this.confirmSignIn}
83              />
84            </Fragment>
85          )
86        }        
87      </View>
88    )
89  }
90}
91
92const styles = StyleSheet.create({
93  input: {
94    width: 350,
95    fontSize: 18,
96    fontWeight: '500',
97    height: 55,
98    backgroundColor: '#42A5F5',
99    margin: 10,
100    color: 'white',
101    padding: 8,
102    borderRadius: 14
103  },
104  container: {
105    flex: 1,
106    justifyContent: 'center',
107    alignItems: 'center'
108  }
109})

فایل SignIn.js

منطق این کامپوننت بسیار مشابه آن چیزی است که در SignUp.js دیدیم و تنها یک تفاوت وجود دارد. زمانی که Auth.signIn را فراخوانی می‌کنیم، مقدار بازگشتی از فراخوانی متد را در حالت (State) خود ذخیره می‌کنیم تا بعدتر در Auth.confirmSignIn استفاده کنیم. زمانی که (Auth.confirmSignIn(user, confirmationCode را فراخوانی می‌کنیم، این شیء کاربر را همراه با کد احراز هویت دریافتی از MFA به آن ارسال می‌کنیم.

فایل Initializing.js

زمانی که کاربر وارد حساب خود در اپلیکیشن شد، می‌توانیم از طریق فراخوانی کردن Auth.currentAuthenticatedUser اطلاعاتی در مورد کاربر بازیابی کنیم. اگر یک کاربر ثبت نام کرده باشد، این تابع موفق خواهد بود و می‌توانیم اپلیکیشن اصلی را بارگذاری کنیم. اگر این رویه ناموفق باشد، می‌توانیم مسیریابی‌های احراز هویت یعنی SignIn و SignUp را بارگذاری کنیم.

برای پیاده‌سازی این وضعیت باید کامپوننت Auth را از AWS Amplify ایمپورت کرده و متد چرخه عمر componentDidMount را به‌روزرسانی کنیم تا کاربر را بررسی کند:

1// Initializing.js
2// previous imports excluded
3import { Auth } from 'aws-amplify'
4export default class Initialising extends React.Component {
5  async componentDidMount() {
6    try {
7      const user = await Auth.currentAuthenticatedUser()
8      console.log('user: ', user)
9      if (user) {
10        goHome()
11      } else {
12        goToAuth()
13      }
14    } catch (err) {
15      console.log('error: ', err)
16      goToAuth()
17    }
18  }
19// rest of class excluded
20}

برای مشاهده نسخه نهایی این کامپوننت به این لینک (+) مراجعه کنید.

فایل Home.js

آخرین کاری که باید انجام دهیم، به‌روزرسانی دکمه SignOut است تا در زمان کلیک شدن، کاربر را عملاً از اپلیکیشن خارج کند. به این منظور می‌توانیم دستگیره onPress را الحاق کنیم تا متد Auth.signOut را از AWS Amplify فراخوانی کند:

1// Home.js
2// previous imports excluded
3import { Auth } from 'aws-amplify'
4export default class Home extends React.Component {
5  // static options omitted
6  logout = async () => {
7    try {
8      await Auth.signOut()
9      goToAuth()
10    } catch (err) {
11      console.log('error signing out...: ', err)
12    }
13  }
14  // rest of class excluded
15}

برای مشاهده نسخه نهایی این کامپوننت به این صفحه (+) مراجعه کنید.

سخن پایانی

راه‌اندازی و اجرای احراز هویت کاربر به کمک ترکیبی از Amazon Cognito و AWS Amplify کار واقعاً سرراستی محسوب می‌شود. تکنیک‌هایی که در این راهنما استفاده کردیم، به همراه کتابخانه React Native Navigation کار می‌کنند و البته با ارائه‌دهندگان خدمات احراز هویت دیگر نیز به خوبی اجرا خواهند شد.

وقتی از ناوبری در ری‌اکت نیتیو صحبت می‌کنیم، دو کتابخانه بسیار کارآمد وجود دارند که یکی React Navigation و دیگری React Native Navigation است. کتابخانه React Navigation نگهداری بسیار خوبی دارد و کاملاً به بلوغ رسیده است. این کتابخانه تقریباً هر چیزی را که بخواهید انجام می‌دهد و تیم نگهداری آن کار فوق‌العاده‌ای در رسیدگی به مشکلات و تبدیل کردن به یک کتابخانه درجه یک انجام داده‌اند.

React Native Navigation نیز گزینه مناسبی محسوب می‌شود و از سوی تیم توسعه‌دهنده به خوبی نگهداری شده است. React Native Navigation نسخه 2 اخیراً وارد فاز آلفا شده و ممکن است برخی قابلیت‌ها هنوز عرضه نشده باشند که در این مورد می‌توانید issue بدهید یا درخواست pull کنید.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۰ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
dabit3
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *