如何使用 Azure AD 验证 VueJS 应用程序?

新手上路,请多包涵

我正在使用 VueJS 2.x 框架设置一个应用程序,它需要通过 Azure Active Directory 服务对用户进行身份验证。我已经有了该服务所需的“登录信息”(Auth 和 Token URL)。

到目前为止,我只遇到过 一篇文章 显示 VueJS 中的设置,但它依赖于第三方服务 (Auth0) - 在过程中添加不必要的卷积。

如果 没有任何允许轻松进行身份验证的 VueJS npm 模块,您将如何进行?或者您是否必须依赖 Vue 之外的库,例如 Adal JS

任何的意见都将会有帮助。

原文由 Coreus 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.2k
2 个回答

为了解决这个问题,我依靠 ADAL JS 。我在 这里 提供了一个 Vue + Vue-Router 示例应用程序 - 但我将在下面包含重要部分。

在你的 package.json 中:

 "dependencies": {
    "adal-angular": "^1.0.15",
    "vue": "^2.5.2",
    "vue-router": "^3.0.1"
},

ADAL JS 库的基本包装器模块:

 import AuthenticationContext from 'adal-angular/lib/adal.js'

const config = {
  tenant: 'your aad tenant',
  clientId: 'your aad application client id',
  redirectUri: 'base uri for this application',
  cacheLocation: 'localStorage'
};

export default {
  authenticationContext: null,
  /**
   * @return {Promise}
   */
  initialize() {
    this.authenticationContext = new AuthenticationContext(config);

    return new Promise((resolve, reject) => {
      if (this.authenticationContext.isCallback(window.location.hash) || window.self !== window.top) {
        // redirect to the location specified in the url params.
        this.authenticationContext.handleWindowCallback();
      }
      else {
        // try pull the user out of local storage
        let user = this.authenticationContext.getCachedUser();

        if (user) {
          resolve();
        }
        else {
          // no user at all - go sign in.
          this.signIn();
        }
      }
    });
  },
  /**
   * @return {Promise.<String>} A promise that resolves to an ADAL token for resource access
   */
  acquireToken() {
    return new Promise((resolve, reject) => {
      this.authenticationContext.acquireToken('<azure active directory resource id>', (error, token) => {
        if (error || !token) {
          return reject(error);
        } else {
          return resolve(token);
        }
      });
    });
  },
  /**
   * Issue an interactive authentication request for the current user and the api resource.
   */
  acquireTokenRedirect() {
    this.authenticationContext.acquireTokenRedirect('<azure active directory resource id>');
  },
  /**
   * @return {Boolean} Indicates if there is a valid, non-expired access token present in localStorage.
   */
  isAuthenticated() {
    // getCachedToken will only return a valid, non-expired token.
    if (this.authenticationContext.getCachedToken(config.clientId)) { return true; }
    return false;
  },
  /**
   * @return An ADAL user profile object.
   */
  getUserProfile() {
    return this.authenticationContext.getCachedUser().profile;
  },
  signIn() {
    this.authenticationContext.login();
  },
  signOut() {
    this.authenticationContext.logOut();
  }
}

在应用程序的入口点(如果您使用 vue-cli,则为 main.js):

 import Vue from 'vue'
import App from './App'
import router from './router'
import authentication from './authentication'

// Init adal authentication - then create Vue app.
authentication.initialize().then(_ => {
  /* eslint-disable no-new */
  new Vue({
    el: '#app',
    router,
    template: '<App/>',
    components: { App }
  });
});

对于您的 Vue 路由器配置:

 import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import authentication from '../authentication'

Vue.use(Router)

const router = new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld,
      meta: {
        requiresAuthentication: true
      }
    }
  ]
})

// Global route guard
router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuthentication)) {
    // this route requires auth, check if logged in
    if (authentication.isAuthenticated()) {
      // only proceed if authenticated.
      next();
    } else {
      authentication.signIn();
    }
  } else {
    next();
  }
});

export default router;

在你的 Vue 组件中:

 import authentication from './authentication'
...
computed: {
  isAuthenticated() {
    return authentication.isAuthenticated();
  }
},
methods: {
  logOut() {
    authentication.signOut();
  }
}

将访问令牌添加到请求标头

下面是一个 vue-resource http 拦截器的例子,但是任何方法都可以。

 Vue.http.interceptors.push(function (request, next) {
  auth.acquireToken().then(token => {
    // Set default request headers for every request
    request.headers.set('Content-Type', 'application/json');
    request.headers.set('Ocp-Apim-Subscription-Key', 'api key');
    request.headers.set('Authorization', 'Bearer ' + token)
    // continue to next interceptor
    next();
  });
});

希望这可以节省一些时间 :)

原文由 matt-ankerson 发布,翻译遵循 CC BY-SA 3.0 许可协议

免责声明: 我是这个插件的作者。

通过 npm 使用 vue-adal

 npm install vue-adal

基本用法

import Adal from 'vue-adal'
Vue.use(Adal, {
// This config gets passed along to Adal, so all settings available to adal can be used here.
  config: {
    // 'common' (multi-tenant gateway) or Azure AD Tenant ID
    tenant: '<guid>',

    // Application ID
    clientId: '<guid>',

    // Host URI
    redirectUri: '<host addr>',

    cacheLocation: 'localStorage'
  },

  // Set this to true for authentication on startup
  requireAuthOnInitialize: true,

  // Pass a vue-router object in to add route hooks with authentication and role checking
  router: router
})
```

重要:确保将路由器上的模式设置为“历史”,这样它就不会使用哈希值!这将对服务器端产生影响。

 new Router({
  mode: 'history', // Required for Adal library
  ... // Rest of router init
})

npm 上有更多使用说明, github 上有说明+ 示例

原文由 survirtual 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏