AWS Amplify教程之五:自定制的验证功能


前面对AWS Amplify进行一个基本的介绍,以及如何为React APP添加用户验证,使用S3存储的功能,使用AWS API功能。下面介绍如何使用Amplify自定义用户验证功能。

AWS Amplify
AWS Amplify

AWS Amplify系列教程:

设定条件路由

由于需要针对登录/未登录用户进行不同的控制,因此需要使用路由。首先安装依赖库:

bash
yarn add react-router-dom

然后在App.js中,设定条件路由:

javascript
import { Switch, Route, BrowserRouter as Router } from 'react-router-dom';

return(
  <Router>
    <div className="App">
      <Header/>

      <Switch>
        <Route exact path='/'>
          <StudentList/>
        </Route>
      </Switch>
    </div>
  </Router>
)

移除withAuthenticator,改为人工控制登录状态

删除以下语句中的withAuthenticator,后面将自己管理是否已经登录的状态:

javascript
export default withAuthenticator(App);

更新App.js:

javascript
function App() {
  const [loggedin, setLoggedin] = usedState(false);

  const isLoggedIn = () => {
    Auth.currentAuthenticatedUser().then(() => {
      setLoggedin(true);
    }).catch(() => {
      setLoggedin(false);
    })
  }

  useEffect(() => {
    isLoggedIn();
  }, [])

}

同时更新自定义的signOut函数:

javascript
const signOut = async () => {
  try {
    await Auth.signOut();
    setLoggedin(false);
  } catch (err) {
    console.log(err);
  }
}

同时可以更新Header:

javascript
{loggedin? (
  <Button onClick={signOut}>
    Sign Out
  </Button>
) : (
  <Link to="/signin">
    <Button>
      Sign In
    </Button>
  </Link>
)}

在App.js中,添加Sign in组件路由:

javascript

const onSignIn = () => {
  setLoggedIn(true);
}
...

<Switch>
  <Route path="/signin">
    <SignIn onSignIn={onSignIn}/>
  </Route>
</Switch>

SignIn组件:

javascript
import React from 'react'
import { Button, TextField } from '@material-ui/core';
import { useHistory } from 'react-route-dom';

const SignIn = ({ onSignIn }) => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const history = useHistory();

  const signIn = async () => {
    try {
      const user = await Auth.signIn(username, password);
      history.push('/');
      onSignIn();
    } catch (err) {
      console.log(err);
    }
  }

  return (
    <div className="signin">
      <TextField id='username' 
                 label="Username"
                 value={username}
                 onChange={e => setUsername(e.target.value)}
                 />
      <TextField id='password' 
                 label="Password"
                 type="password"
                 value={password}
                 onChange={e => setPassword(e.target.value)}
                 />           
      <Button id="signinBtn" onClick="signIn">
        Sign In
      </Button>             
    </div>
  )
}

export default SignIn

对未登录用户进行访问控制

bash
amplify update auth

Walk through all configuration

  • Allow unauthenticated logins? Yes
    其余选项都选择默认设置
bash
amplify push

在AWS控制台更新配置

进入Cognito -> Identity Pool -> Edit Identify pool -> Unauthenticated role

进入IAM,找到Unauthenticated role -> Permissions -> Attach policies -> Add inline policy -> JSON

然后以下模板更新policy:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": "appsync:GraphQL",
      "Resource": "arn:aws:appsync:<REGION>:<ACCOUNT>:apis/<APP ID>/types/<Query | Mutation>/fields/<METHOD>"
    }
  ]
}

比如这样将允许未授权用户调用listStudents方法:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": "appsync:GraphQL",
      "Resource": "arn:aws:appsync:eu-west-1:YOUR_AWS_ACCOUNT_ID:apis/YOUR_APP_SYNC_APP_ID/types/Query/fields/listStudents"
    }
  ]
}

同时还可以定义类似的policy,比如对S3的访问:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3::::<BUCKET>/public"
    }
  ]
}

然后单击“Review Policy”, 输入名字后保存。

回到AWS AppSync控制台,将”Default authorization model”更改为”AWS Identity and Access Management (IAM)”,保存。

更新代码

这时需要将前面的fetchStudents方法由:

javascript
const studentData = await API.graphql(graphqlOperation(listStudents));

更新为:

javascript
const studentData = await API.graphql({
  query: listStudents,
  authMode: 'AWS_IAM'
});

但这时会有一个问题,登录的用户反倒无法访问相应资源了。

进入IAM,找到authorizedRole,”Public_policy_xxxxx”

可以发现,这里缺少对AppSync访问的授权。

同样,添加相应的Policy就可以了:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": "appsync:GraphQL",
      "Resource": [
        "arn:aws:appsync:eu-west-1:YOUR_AWS_ACCOUNT_ID:apis/YOUR_APP_SYNC_APP_ID/types/Query/fields/listStudents",
        "arn:aws:appsync:eu-west-1:YOUR_AWS_ACCOUNT_ID:apis/YOUR_APP_SYNC_APP_ID/types/Mutation/fields/createStudent""arn:aws:appsync:eu-west-1:YOUR_AWS_ACCOUNT_ID:apis/YOUR_APP_SYNC_APP_ID/types/Mutation/fields/updateStudent"
      ]
    }
  ]
}

同理,在应用程序中调用mutation时,还需要更新为:

javascript
await API.graphql({
  query: updateStudent,
  variables: {input: student},
  authMode: 'AWS_IAM'
}) 

文章作者: 逻思
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 逻思 !