将Amazon Cognito与单页面应用程序(Vue.js)集成

在本文中,我们将研究使用OAuth协议通过Amazon Cognito对单页应用程序(使用Vue.js构建)进行身份验证。 在上一篇文章中,我们将服务器端应用程序与Amazon Cognito集成在一起。

搭建单页应用程序

我们将使用vue-cli创建一个空的Vuejs应用程序。 可以按照此处的说明安装Vue CLI。

让我们通过发出以下命令来创建一个名为aws-cognito-spa-demo的空应用程序:

 vue create aws-cognito-spa-demo 

系统将提示您选择插件

亚马逊Cognito

创建应用程序后,您可以导航到该目录并发出命令以运行该应用程序

 cd aws-cognito-spa-demo  npm instal  npm run serve 

您将在http:// localhost:8080运行该应用程序

安装其他依赖项

我们将安装用于该应用程序的必需节点软件包:

 npm install --save amazon-cognito-auth-js  npm install --save amazon-cognito-identity-js  npm install --save vue-router  npm install --save axios 

在Amazon Cognito中创建新的App Client

我们将通过Amazon Cognito控制台创建一个名为test-spa-client的新App客户test-spa-client ,如下所示:

亚马逊Cognito

通过提供回调URL,注销URL,允许的OAUth流和OAuth范围的值,导航到“应用程序客户端设置”以更新创建的客户端的设置:

亚马逊Cognito

我们使用隐式授予作为SPA应用程序的OAuth流。

创建环境变量

我们将与Amazon Cognito相关的设置存储在属性文件中,并且Vue CLI将在应用程序运行时使其在环境变量中可用。 在此处可以找到有关在Vue JS应用程序中定义环境变量的更多信息。

我们将在.env文件中存储通用的应用程序设置,例如cognito重定向URI,注销URI和.env一些本地设置。 .env。*。local和.env.local文件从git中被忽略。 因此,您不必将本地设置提交到版本控制。

 # In .env  VUE_APP_COGNITO_REDIRECT_URI=http: //localhost:8080/login/oauth2/code/cognito  VUE_APP_COGNITO_REDIRECT_URI_SIGNOUT=http: //localhost:8080/logout  VUE_APP_APP_URL=http: //localhost:8080 

然后是.env.local中的以下内容:

 VUE_APP_COGNITO_USERPOOL_ID=<cognito userpool id>  VUE_APP_COGNITO_APP_DOMAIN=<cognito app domain>  VUE_APP_COGNITO_CLIENT_ID=<app client id> 

创建用户信息存储

我们将使用全局JSON对象存储登录的用户信息。 这是使用Vuex的另一种方法。 让我们在src/app/user-info-store.js创建JSON对象:

 var state = { 
   cognitoInfo: {}, 
   loggedIn: false , 
   loadingState: true , 
   errorLoadingState: false  }  function setLoggedIn(newValue) { 
   state.loggedIn = newValue;  }  function setLoggedOut() { 
   state.loggedIn = false ; 
   state.cognitoInfo = {};  }  function setCognitoInfo(newValue){ 
   state.cognitoInfo = newValue;  }  export default { 
   state: state, 
   setLoggedIn: setLoggedIn, 
   setLoggedOut: setLoggedOut, 
   setCognitoInfo: setCognitoInfo  } 

Amazon Cognito API的包装

让我们为Amazon Cognito API创建包装器src/app/auth.js ,这将简化诸如构建CognitoAuth对象,登录和注销的操作:

 /* eslint-disable */  {CognitoAuth, StorageHelper} from 'amazon-cognito-auth-js' import {CognitoAuth, StorageHelper} from ;  IndexRouter from '../router/index' import IndexRouter from ;  UserInfoStore from './user-info-store' import UserInfoStore from ;  UserInfoApi from './user-info-api' import UserInfoApi from ;  const CLIENT_ID = process.env.VUE_APP_COGNITO_CLIENT_ID;  const APP_DOMAIN = process.env.VUE_APP_COGNITO_APP_DOMAIN;  const REDIRECT_URI = process.env.VUE_APP_COGNITO_REDIRECT_URI;  const USERPOOL_ID = process.env.VUE_APP_COGNITO_USERPOOL_ID;  const REDIRECT_URI_SIGNOUT = process.env.VUE_APP_COGNITO_REDIRECT_URI_SIGNOUT;  const APP_URL = process.env.VUE_APP_APP_URL;  var authData = { 
     ClientId : CLIENT_ID, // Your client id here 
     AppWebDomain : APP_DOMAIN, 
     TokenScopesArray : [ 'openid' , 'email' ], 
     RedirectUriSignIn : REDIRECT_URI, 
     RedirectUriSignOut : REDIRECT_URI_SIGNOUT, 
     UserPoolId : USERPOOL_ID,  }  var auth = new CognitoAuth(authData);  auth.userhandler = { 
     onSuccess: function(result) { 
         console.log( "On Success result" , result); 
         UserInfoStore.setLoggedIn( true ); 
         UserInfoApi.getUserInfo().then(response => { 
             IndexRouter.push( '/' ); 
         });                 
     }, 
     onFailure: function(err) { 
         UserInfoStore.setLoggedOut(); 
         IndexRouter.go({ path: '/error' , query: { message: 'Login failed due to ' + err } }); 'Login failed due to ' + err } }); 
     }  };  function getUserInfoStorageKey(){ 
     var keyPrefix = 'CognitoIdentityServiceProvider.' + auth.getClientId(); 
     var tokenUserName = auth.signInUserSession.getAccessToken().getUsername(); 
     var userInfoKey = keyPrefix + '.' + tokenUserName + '.userInfo' ; 
     return userInfoKey;  }  var storageHelper = new StorageHelper();  var storage = storageHelper.getStorage();  export default { 
     auth: auth, 
     login(){ 
         auth.getSession(); 
     }, 
     logout(){ 
         if (auth.isUserSignedIn()) { 
             var userInfoKey = this .getUserInfoStorageKey(); 
             auth.signOut(); 
             storage.removeItem(userInfoKey); 
         } 
     }, 
     getUserInfoStorageKey,  } 

从Amazon Cognito获取用户信息

身份验证之后,我们可以使用访问令牌来获取有关登录用户的信息。为此,我们必须向端点发出GET请求: https://<app domain>/oauth2/userInfo 。 我们在src/app/user-info.js创建了一个实用程序方法getUserInfo() ,如下所示:

 axios from 'axios' import axios from ;  auth from './auth' import auth from ;  export default { 
     getUserInfo(){ 
         var jwtToken = auth.auth.getSignInUserSession().getAccessToken().jwtToken; 
         const USERINFO_URL = ' https:// ' +auth.auth.getAppWebDomain() + '/oauth2/userInfo' ; 
         var requestData = { 
             headers: { 
                 'Authorization' : 'Bearer ' + jwtToken 
             } 
         } 
         return axios.get(USERINFO_URL, requestData).then(response => { 
             return response.data; 
         }); 
     }  } 

上面部分编写的Cognito包装器已使用此API。

创建Vue组件

让我们为以下目的创建一些Vue组件:

  • 显示已登录的用户信息
  • 显示注销成功
  • 错误处理组件

我们将使用Vue路由器将URL路径映射到Vue组件。 组件定义如下所示:

Home组件

 <template> 
     <div class = "row" > 
         <div class = "col" > 
             <h3>Welcome, </h3> 
             <div class = "alert alert-info" > 
                 {{userInfo}} 
             </div> 
             <router-link to= "/logout" > 
                 Logout 
             </router-link> 
         </div> 
     </div>  </template>  <script>  UserInfoStore from '../app/user-info-store' import UserInfoStore from ;  export default { 
     name: 'Home' , 
     data: function() { 
         return { 
             userInfo: UserInfoStore.state.cognitoInfo 
         } 
     }  }  </script>  <style>  </style> 

LogoutSuccess组件:

 <template>  <div class = "row" > 
     <div class = "col" > 
         <h2>Logged Out successfully</h2> 
         <router-link to= "/login" >Login</router-link> 
     </div>  </div>  </template>  <script>  export default { 
     mounted: function(){         
     }  }  </script> 

错误组件:

 <template> 
     <div class = "alert alert-danger" > 
         {{message}} 
     </div>  </template>  <script>  export default { 
     data: function(){ 
         return { 
             message: "" 
         } 
     }, 
     mounted(){ 
         this .message = this .$route.query.message; 
     }  }  </script> 

设置路由器

如前一节所述,我们将使用Vue Router将URL路径映射到Vue组件。 我们将在router/index.js设置路由器配置,如下所示:

 /* eslint-disable */  Vue from 'vue' import Vue from  Router from 'vue-router' import Router from  Home from '@/components/Home' import Home from  auth from '../app/auth' import auth from ;  LogoutSuccess from '@/components/LogoutSuccess' import LogoutSuccess from ;  UserInfoStore from '../app/user-info-store' import UserInfoStore from ;  UserInfoApi from '../app/user-info-api' import UserInfoApi from ;  ErrorComponent from '@/components/Error' import ErrorComponent from ;  Vue.use(Router)  function requireAuth(to, from, next) {   
   if (!auth.auth.isUserSignedIn()) { 
       UserInfoStore.setLoggedIn( false ); 
       next({ 
       path: '/login' , 
       query: { redirect: to.fullPath } 
       }); 
   } else { 
     UserInfoApi.getUserInfo().then(response => { 
       UserInfoStore.setLoggedIn( true ); 
       UserInfoStore.setCognitoInfo(response); 
       next(); 
     });       
   }  }  export default new Router({ 
   mode: 'history' , 
   base: '/' , 
   routes: [ 
     { 
       path: '/' , 
       name: 'Home' , 
       component: Home, 
       beforeEnter: requireAuth 
     }, 
     { 
       path: '/login' , beforeEnter(to, from, next){ 
         auth.auth.getSession(); 
       } 
     }, 
     { 
       path: '/login/oauth2/code/cognito' , beforeEnter(to, from, next){ 
         var currUrl = window.location.href;         
         //console.log(currUrl); 
         auth.auth.parseCognitoWebResponse(currUrl); 
         //next(); 
       } 
     }, 
     { 
       path: '/logout' , component: LogoutSuccess, beforeEnter(to, from, next){ 
         auth.logout(); 
         next(); 
       } 
     }, 
     { 
       path: '/error' , component: ErrorComponent 
     } 
   ]  }) 

我们利用路由对象的beforeEnter属性添加渲染组件所需的所有先决条件。 然后在此属性中,检查用户是否使用我们创建的Cognito包装器登录。 因此,对于需要保护的路径,我们可以定义beforeEnter属性。

创建的默认应用程序具有一个App.vue组件,它将成为我们的根组件。 我们使用<router-view/>标记表示此处HTML将基于路由器配置中路径解析到的组件。

因此,我们的App.vue版本如下所示:

 <template> 
   <div id= "app" > 
     <img alt= "Vue logo" src= "./assets/logo.png" > 
     <div class = "contents" > 
       <router-view/> 
     </div> 
   </div>  </template>  <script>  export default { 
   name: 'app'  }  </script>  <style>  #app { 
   font-family: 'Avenir' , Helvetica, Arial, sans-serif; 
   -webkit-font-smoothing: antialiased; 
   -moz-osx-font-smoothing: grayscale; 
   text-align: center; 
   color: #2c3e50; 
   margin-top: 60px;  }  </style> 

然后,我们更新src/main.js以引用包含路由器配置的目录,如下所示:

 Vue from 'vue' import Vue from  App from './App.vue' import App from  router from './router' import router from  Vue.config.productionTip = false  new Vue({ 
   render: h => h(App), 
   router  }).$mount( '#app' ) 

运行应用程序

您可以通过发出以下命令来运行该应用程序: npm run serve 。 导航到localhost:8080将带您进入Cognito登录屏幕:

亚马逊Cognito

输入您已在用户池中注册的用户的用户名和密码,甚至可以注册一个新用户。 登录后,您将被重定向回Vue JS应用:

亚马逊Cognito

注销链接将注销用户。

完整的代码可以在Github仓库中找到

翻译自: https://www.javacodegeeks.com/2019/04/amazon-cognito-single-page-application-vue.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值