Vue.js JWT 模式

JWTs或JSON Web Tokens是安全地存储可验证的会话状态在客户端上的一种流行的方法,而不需要具有状态的服务器。 它们最近随着无服务器网络应用程序的兴起而变得非常受欢迎。 JWTs是您的应用程序状态的核心部分,但它们既是代币,也是可解析的数据。 因此,我们如何以两种方式使用它们? 这里有几种模式可以让在Vue.js中与JWT合作成为一种风潮。

<$>[注] 在本指南中,我们将假装我们有一个API终端,它以JWT作为字符串响应在GET http://localhost/vuejs-jwt-example/auth?u=username&p=password

<$>[警告]如何在整个会话中坚持JWT留给您,只需注意在 localStorage中存储敏感数据的危险(https://dev.to/rdegges/please-stop-using-local-storage-1i04)! <$>

没有Vuex

也许我会做的最重要的建议是永远不要存储JWT的解析版本.分开存储一个字符串和一个解析对象,就是为痛苦的世界设置自己。

相反,使用 Vue.js 的 计算属性 创建从字符串每当字符串被更新时的按需对象。

有了基本的 Vue.js 组件,它可能看起来像这样:

 1<template>
 2  <div>
 3    <p>JWT: {{jwt}}</p>
 4    <p>User ID: {{jwtData.sub}}</p>
 5    <p>Issuer: {{jwtData.iss}}</p>
 6    <button @click.native="doSomethingWithJWT()">Do Something</button>
 7  </div>
 8</template>
 9
10<script>
11export default {
12  data() {
13    return {
14      jwt: ''
15    }
16  },
17
18  computed: {
19    // this.jwtData will update whenever this.jwt changes.
20    jwtData() {
21      // JWT's are two base64-encoded JSON objects and a trailing signature
22      // joined by periods. The middle section is the data payload.
23      if (this.jwt) return JSON.parse(atob(this.jwt.split('.')[1]));
24      return {};
25    }
26  },
27
28  methods: {
29    async fetchJWT() {
30      // Error handling and such omitted here for simplicity.
31      const res = await fetch(`http://localhost/vuejs-jwt-example/auth?u=username&p=password`);
32      this.jwt = await res.text();
33    },
34
35    async doSomethingWithJWT() {
36      const res = await fetch(`http://localhost/vuejs-jwt-example/do-something`, {
37        method: 'POST',
38        headers: new Headers({
39          Authorization: `Bearer: ${this.jwt}`
40        })
41      });
42      // Do stuff with res here.
43    }
44  },
45
46  mounted() {
47    this.fetchJWT();
48  }
49}
50</script>

关于Vuex

如果您使用的是 Vuex,您可以使用基于 Vuex 操作和 getter 的类似模式。

以下是一个例子 user vuex 模块,允许您获取 JWT,并以字符串和对象形式访问它。

 1export const UserModule = {
 2  state: {
 3    currentJWT: ''
 4  },
 5
 6  getters: {
 7    jwt: state => state.currentJWT,
 8    jwtData: (state, getters) => state.currentJWT ? JSON.parse(atob(getters.jwt.split('.')[1])) : null,
 9    jwtSubject: (state, getters) => getters.jwtData ? getters.jwtData.sub : null,
10    jwtIssuer: (state, getters) => getters.jwtData ? getters.jwtData.iss : null
11  },
12
13  mutations: {
14    setJWT(state, jwt) {
15      // When this updates, the getters and anything bound to them updates as well.
16      state.currentJWT = jwt;
17    }
18  }
19
20  actions: {
21    async fetchJWT ({ commit }, { username, password }) {
22      // Perform the HTTP request.
23      const res = await fetch(`http://localhost/vuejs-jwt-example/auth?u=${username}&p=${password}`);
24      // Calls the mutation defined to update the state's JWT.
25      commit('setJWT', await res.text());
26    },
27  }
28}

这可以在类似于我们上面写的组件中使用,如下:

 1<template>
 2  <div>
 3    <p>JWT: {{jwt}}</p>
 4    <p>User ID: {{jwtSubject}}</p>
 5    <p>Issuer: {{jwtIssuer}}</p>
 6    <button @click.native="doSomethingWithJWT()">Do Something</button>
 7  </div>
 8</template>
 9
10<script>
11import { mapGetters, mapActions } from 'vuex';
12
13export default {
14  computed: {
15    ...mapGetters([
16      'jwt',
17      'jwtSubject',
18      'jwtIssuer'
19    ])
20  },
21
22  methods: {
23    ...mapActions([
24      `fetchJWT`
25    ]),
26
27    // The implementation here doesn't change at all!
28    async doSomethingWithJWT() {
29      const res = await fetch(`http://localhost/vuejs-jwt-example/do-something`, {
30        method: 'POST',
31        headers: new Headers({
32          Authorization: `Bearer: ${this.jwt}`
33        })
34      });
35      // Do stuff with res here.
36    }
37  },
38
39  mounted() {
40    this.fetchJWT({
41      // #Security...
42      username: 'username',
43      password: 'password'
44    });
45  }
46}
47</script>

这里展示的方法的好处在于,JWT本身只以字符串形式存储和更新(用于API请求和验证的表格)。

Published At
Categories with 技术
Tagged with
comments powered by Disqus