├── .gitignore ├── README.md ├── jwt-pure-js ├── README.md ├── js │ ├── lib │ │ ├── jquery-1.12.4.js │ │ └── vue.js │ └── util │ │ └── util.js └── views │ ├── index.html │ └── login.html └── vue-jwt-demo ├── README.md ├── index.html ├── npm-debug.log ├── package-lock.json ├── package.json ├── src ├── App.vue ├── assets │ └── logo.png ├── auth │ └── auth.js ├── component │ ├── Home.vue │ └── Login.vue ├── main.js └── util │ └── net.js └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | vue-jwt-demo/node_modules 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # 说明 3 | 4 | 本项目有2个关于前后端分离的前端实现 5 | 6 | 1. vue-jwt-demo: 使用vue js构建 7 | 2. jwt-pure-js: 使用传统js构建 8 | 9 | **2018-08修改:** 10 | 11 | 将token放在header里改为放在参数里传递 12 | -------------------------------------------------------------------------------- /jwt-pure-js/README.md: -------------------------------------------------------------------------------- 1 | # 介绍 2 | 纯的js+jquery+vue.js 3 | -------------------------------------------------------------------------------- /jwt-pure-js/js/util/util.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * 网络请求封装模块 4 | */ 5 | var net = { 6 | HOST: "http://localhost:8081", 7 | /** 8 | * JSON请求,后台使用RequestBody接收数据 9 | */ 10 | postJson: function (url, data, callback) { 11 | $.ajax({ 12 | url: net.HOST + url, 13 | type: "POST", 14 | dataType: "json", 15 | contentType: "application/json;charset=utf-8", 16 | data: JSON.stringify(data), 17 | success: function (re) { 18 | if (re.ok) { 19 | callback(re); 20 | } else { 21 | console.log(re.msg); 22 | } 23 | }, 24 | error: function (e) { 25 | console.log(e) 26 | alert("error") 27 | } 28 | }) 29 | } 30 | } 31 | 32 | /** 33 | * 本地存储模块 34 | */ 35 | var storage = { 36 | TOKEN_KEY: "token_key", 37 | /** 38 | * 存储token到cookie 39 | */ 40 | tokenStore: function (token) { 41 | console.log(document.cookie) 42 | // cookie.setCookie(storage.TOKEN_KEY, token, 1); 43 | sessionStorage.TOKEN_KEY = token; 44 | }, 45 | /** 46 | * 获取token 47 | */ 48 | tokenGet: function () { 49 | // var token = cookie.getCookie(storage.TOKEN_KEY); 50 | // return token; 51 | return sessionStorage.TOKEN_KEY; 52 | }, 53 | isTokenValid: function () { 54 | if (storage.tokenGet() === null) { 55 | return false; 56 | } 57 | return true; 58 | } 59 | } 60 | 61 | /** 62 | * js操作cookie工具类 63 | */ 64 | var cookie = { 65 | //写cookies 66 | setCookie: function (cname, cvalue, exdays) { 67 | var d = new Date(); 68 | d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); 69 | var expires = "expires=" + d.toGMTString(); 70 | document.cookie = cname + "=" + cvalue + "; " + expires; 71 | }, 72 | //读取cookies 73 | getCookie: function (cname) { 74 | var name = cname + "="; 75 | var ca = document.cookie.split(';'); 76 | for (var i = 0; i < ca.length; i++) { 77 | var c = ca[i].trim(); 78 | if (c.indexOf(name) == 0) { return c.substring(name.length, c.length); } 79 | } 80 | return ""; 81 | }, 82 | //删除cookies 83 | delCookie: function (name) { 84 | var exp = new Date(); 85 | exp.setTime(exp.getTime() - 1); 86 | var cval = cookie.getCookie(name); 87 | if (cval != null) { 88 | document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString(); 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /jwt-pure-js/views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue.js learn 7 | 8 | 9 | 10 | 11 |
12 | {{email}} 13 | 14 |
15 |
16 | {{message}} 17 |
18 | 19 |
20 | move on 21 |
22 | 23 |
24 |

你看见我了

25 |
26 |
27 |
    28 |
  1. {{todo.text}}
  2. 29 |
30 |
31 |
32 |

{{message}}

33 | 34 |
35 |
36 |

{{msg}}

37 | 38 |
39 |
40 |
    41 | 42 | 43 |
44 |
45 | 46 | 47 | 48 | 49 | 50 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /jwt-pure-js/views/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Login 7 | 8 | 9 | 10 |

前后端分离登录

11 |
12 | Name: 13 | Password: 14 | 15 | 16 |

{{error}}

17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /vue-jwt-demo/README.md: -------------------------------------------------------------------------------- 1 | # vue-jwt-demo 2 | 3 | > 一个最简单的vue.js项目,实现了前后端分离的基本功能 4 | > 对应的java后台:https://github.com/jimolonely/AuthServer 5 | 6 | ## Build Setup 7 | 8 | ``` bash 9 | # install dependencies 10 | npm install 11 | 12 | # serve with hot reload at localhost:8080 13 | npm run dev 14 | 15 | # build for production with minification 16 | npm run build 17 | ``` 18 | 19 | For detailed explanation on how things work, consult the [docs for vue-loader](http://vuejs.github.io/vue-loader). 20 | -------------------------------------------------------------------------------- /vue-jwt-demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | vue-jwt-demo 6 | 7 | 8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /vue-jwt-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-jwt-demo", 3 | "description": "A Vue.js project", 4 | "version": "1.0.0", 5 | "author": "jimolonely", 6 | "private": true, 7 | "scripts": { 8 | "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot", 9 | "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" 10 | }, 11 | "dependencies": { 12 | "jquery": "^3.2.1", 13 | "vue": "^2.5.17", 14 | "vue-resource": "^1.5.1", 15 | "vue-router": "^3.0.1" 16 | }, 17 | "devDependencies": { 18 | "babel-core": "^6.0.0", 19 | "babel-loader": "^6.0.0", 20 | "babel-preset-latest": "^6.0.0", 21 | "cross-env": "^3.0.0", 22 | "css-loader": "^0.25.0", 23 | "file-loader": "^0.9.0", 24 | "vue-loader": "^11.1.4", 25 | "vue-template-compiler": "^2.2.1", 26 | "webpack": "^2.2.0", 27 | "webpack-dev-server": "^2.2.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /vue-jwt-demo/src/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 18 | 19 | 47 | -------------------------------------------------------------------------------- /vue-jwt-demo/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimolonely/vue-jwt-demo/1b028cb051302ac07c2d18d9e5ce7a3692a3799b/vue-jwt-demo/src/assets/logo.png -------------------------------------------------------------------------------- /vue-jwt-demo/src/auth/auth.js: -------------------------------------------------------------------------------- 1 | 2 | const SERVER_URL = 'http://localhost:8081' 3 | const LOGIN_URL = SERVER_URL + '/user/login' 4 | 5 | import net from '../util/net'; 6 | 7 | export default { 8 | data: { 9 | authenticated: false 10 | }, 11 | // login(context, info) { 12 | // net.postJson('/user/login', info, function (token) { 13 | // localStorage.setItem('token', token); 14 | // this.$router.push('home'); 15 | // }) 16 | // context.$http.post(LOGIN_URL, info).then(function (data) { 17 | // console.log(data) 18 | // var re = data.body; 19 | // console.log(re.ok); 20 | // if (re.ok) { 21 | // localStorage.setItem('token', re.data); 22 | // this.authenticated = true 23 | // this.$router.push('home') 24 | // } else { 25 | // console.log(re) 26 | // } 27 | // }, function (err) { 28 | // console.log(err + "," + err.body.message) 29 | // context.error = err.body.message 30 | // }) 31 | // }, 32 | getAuthHeader() { 33 | return { 34 | 'Authorization': 'Bearer ' + localStorage.getItem('token') 35 | } 36 | }, 37 | checkAuth(context) { 38 | var token = localStorage.getItem('token') 39 | if (token) { 40 | this.authenticated = true 41 | } else { 42 | this.authenticated = false 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /vue-jwt-demo/src/component/Home.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 71 | 72 | 91 | -------------------------------------------------------------------------------- /vue-jwt-demo/src/component/Login.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 52 | -------------------------------------------------------------------------------- /vue-jwt-demo/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import Login from './component/Login.vue' 4 | import Home from './component/Home.vue' 5 | import VueRouter from 'vue-router' 6 | import VueResource from 'vue-resource' 7 | import auth from './auth/auth' 8 | 9 | Vue.use(VueRouter) 10 | Vue.use(VueResource) 11 | 12 | //在启动APP时进行校验是否有token 13 | auth.checkAuth() 14 | 15 | const routes= [ 16 | { 17 | path:'/',redirect:'/login' 18 | }, 19 | { 20 | path:'/login',component:Login 21 | }, 22 | { 23 | path:'/home',component:Home 24 | } 25 | ] 26 | 27 | const router = new VueRouter({ 28 | routes 29 | }) 30 | new Vue({ 31 | router, 32 | render: h => h(App) 33 | }).$mount('#app') 34 | -------------------------------------------------------------------------------- /vue-jwt-demo/src/util/net.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 本工具类与网络相关 3 | */ 4 | import $ from 'jquery'; 5 | 6 | const SERVER_URL = 'http://localhost:8081/' 7 | 8 | export default { 9 | /** 10 | * 检查token是否合法,需要服务器认证 11 | */ 12 | isTokenValid() { 13 | var token = localStorage.getItem('token'); 14 | if (token) { 15 | this.get("user/checkToken?token=" + token, function () { 16 | return true; 17 | }) 18 | } else { 19 | console.log("token不存在") 20 | this.$router.push('login'); 21 | } 22 | }, 23 | /** 24 | * token放在header里后台接受不到,放在参数里一起传递 25 | */ 26 | postJson(url, json, callback) { 27 | var token = localStorage.getItem('token'); 28 | if (token || url === "user/login") { 29 | json.Authorization = 'Bearer ' + token; 30 | console.log(json) 31 | $.ajax({ 32 | url: SERVER_URL + url, 33 | type: 'POST', 34 | dataType: 'json', 35 | contentType: 'application/json;charset=utf-8', 36 | data: JSON.stringify(json), 37 | success: function (re) { 38 | console.log(re) 39 | if (re.ok) { 40 | callback(re.data); 41 | } else { 42 | alert(re.msg); 43 | } 44 | }, 45 | error: function (e) { 46 | console.log(e) 47 | } 48 | }) 49 | } else { 50 | console.log("token不存在") 51 | this.$router.push('login'); 52 | } 53 | }, 54 | get(url, callback, context) { 55 | var token = localStorage.getItem('token'); 56 | if (token) { 57 | $.ajax({ 58 | url: SERVER_URL + url, 59 | type: "GET", 60 | beforeSend: function (xhr) { 61 | xhr.setRequestHeader("Authorization", 'Bearer ' + token); 62 | }, 63 | data: { 64 | Authorization: 'Bearer ' + token 65 | } 66 | }).then(function (re, status, jqxhr) { 67 | console.log(jqxhr); 68 | console.log(status); 69 | console.log(re) 70 | if (re.ok) { 71 | callback(re.data); 72 | } else { 73 | alert(re.msg); 74 | } 75 | }); 76 | 77 | // $.ajax({ 78 | // url: SERVER_URL + url, 79 | // type: 'GET', 80 | // dataType: 'JSON', 81 | // // beforeSend: function (xhr) { 82 | // // xhr.setRequestHeader("Authorization", 'Bearer ' + token); 83 | // // }, 84 | // headers: { 85 | // "Authorization": "Bearer " + token 86 | // }, 87 | // success: function (re) { 88 | // if (re.ok) { 89 | // callback(re.data); 90 | // } else { 91 | // alert(re.msg); 92 | // } 93 | // }, 94 | // error: function (e) { 95 | // console.log(e) 96 | // } 97 | // }) 98 | } else { 99 | console.log("token不存在") 100 | context.$router.push('login'); 101 | } 102 | }, 103 | post(url, json, callback, context) { 104 | var token = localStorage.getItem('token'); 105 | if (token) { 106 | json.Authorization = 'Bearer ' + token; 107 | $.ajax({ 108 | url: SERVER_URL + url, 109 | type: 'POST', 110 | data: json, 111 | success: function (re) { 112 | console.log(re) 113 | if (re.ok) { 114 | callback(re.data); 115 | } else { 116 | alert(re.msg); 117 | } 118 | }, 119 | error: function (e) { 120 | console.log(e) 121 | } 122 | }) 123 | } else { 124 | console.log("token不存在") 125 | context.$router.push('login'); 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /vue-jwt-demo/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var webpack = require('webpack') 3 | module.exports = { 4 | entry: './src/main.js', 5 | output: { 6 | path: path.resolve(__dirname, './dist'), 7 | publicPath: '/dist/', 8 | filename: 'build.js' 9 | }, 10 | module: { 11 | rules: [ 12 | { 13 | test: /\.vue$/, 14 | loader: 'vue-loader', 15 | options: { 16 | loaders: { 17 | } 18 | // other vue-loader options go here 19 | } 20 | }, 21 | { 22 | test: /\.js$/, 23 | loader: 'babel-loader', 24 | exclude: /node_modules/ 25 | }, 26 | { 27 | test: /\.(png|jpg|gif|svg)$/, 28 | loader: 'file-loader', 29 | options: { 30 | name: '[name].[ext]?[hash]' 31 | } 32 | } 33 | ] 34 | }, 35 | resolve: { 36 | alias: { 37 | 'vue$': 'vue/dist/vue.esm.js' 38 | } 39 | }, 40 | devServer: { 41 | historyApiFallback: true, 42 | noInfo: true 43 | }, 44 | performance: { 45 | hints: false 46 | }, 47 | devtool: '#eval-source-map' 48 | } 49 | 50 | if (process.env.NODE_ENV === 'production') { 51 | module.exports.devtool = '#source-map' 52 | // http://vue-loader.vuejs.org/en/workflow/production.html 53 | module.exports.plugins = (module.exports.plugins || []).concat([ 54 | new webpack.DefinePlugin({ 55 | 'process.env': { 56 | NODE_ENV: '"production"' 57 | } 58 | }), 59 | new webpack.optimize.UglifyJsPlugin({ 60 | sourceMap: true, 61 | compress: { 62 | warnings: false 63 | } 64 | }), 65 | new webpack.LoaderOptionsPlugin({ 66 | minimize: true 67 | }) 68 | ]) 69 | } 70 | --------------------------------------------------------------------------------