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请求和验证的表格)。