diff --git a/.doc/contents/Update/README.md b/.doc/contents/Update/README.md new file mode 100644 index 0000000..1fe6bea --- /dev/null +++ b/.doc/contents/Update/README.md @@ -0,0 +1,19 @@ + +## 更新日志 + +### 2020-07-15 +> 重要内容更新:权限分配页中,按钮展示优化,去掉了 `_{id}` 非必要部分. [4f74b43](https://github.com/anjoy8/Blog.Admin/commit/4f74b43ba0cfa59166391cdfe01b2d4e8492fce5) +> 注意要保证后端代码同步更新。 + + +### 2020-07-13 +> 重要内容更新:左侧导航条支持外链(必须满足正确的 `URL` 要求,比如带 `Http` 协议) [7d822c9](https://github.com/anjoy8/Blog.Admin/commit/7d822c987c39ec7b00deb1c5b1c54c06b023f928) + + +### 2020-05-01 +> 重要内容更新:集成按钮级别权限 + + +### 2020-04-30 +> 新增:主分支,通过global.js配置,一键切换JWT和Ids4认证授权模式 + diff --git a/.doc/contents/guide/getting-started.md b/.doc/contents/guide/getting-started.md index c79b627..41100af 100644 --- a/.doc/contents/guide/getting-started.md +++ b/.doc/contents/guide/getting-started.md @@ -40,32 +40,4 @@ Gitee(国内) 下载 [https://gitee.com/laozhangIsPhi/Blog.Admin](https://gi 根目录会出现一个 `dist` 文件夹, 然后拷贝到服务器,用 `Nginx` 或者 `IIS` 进行代理即可。 -### Nginx 部署 -1. 直接执行 `build` 命令后,把 `dist` 文件夹拷贝到服务器,然后配置 `nginx` 即可; -2. 重点是在 `nginx` 中,需要做跨域代理,比如这样的: - -``` - location /api/ { - rewrite ^.+apb/?(.*)$ /$1 break; - include uwsgi_params; - proxy_pass http://localhost:8081; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - #proxy_set_header Connection "upgrade"; - #proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } -``` - -### IIS 部署 - -1. 如果使用 `IIS` 部署的话,就只能使用后端 `CORS` 跨域了,必须保证你的后端项目已经配置好了前端的端口,来允许前端项目能访问,具体的可以查看我的 `Blog.Core` 后端项目中的 `appsettings.json` 中 `Startup/Cors/IPs` 下的配置; -2. 同时,我们请求后端的 `api` 就必须使用绝对路径了,因此,我们需要在 `api.js` 文件中,修改 `base` ,配置为后端项目的端口; - - -### 页面刷新 404 问题 - -具体的查看我的文章: -https://www.cnblogs.com/laozhang-is-phi/p/beautifulPublish-mostBugs.html#autoid-3-10-0 diff --git a/package-lock.json b/package-lock.json index f4543ab..c43414c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2589,8 +2589,7 @@ "base64-js": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", - "dev": true + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" }, "batch": { "version": "0.6.1", @@ -3894,6 +3893,11 @@ "randomfill": "^1.0.3" } }, + "crypto-js": { + "version": "3.1.9-1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz", + "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=" + }, "css": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", @@ -9308,6 +9312,24 @@ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "dev": true }, + "oidc-client": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/oidc-client/-/oidc-client-1.10.1.tgz", + "integrity": "sha512-/QB5Nl7c9GmT9ir1E+OVY3+yZZnuk7Qa9ZEAJqSvDq0bAyAU9KAgeKipTEfKjGdGLTeOLy9FRWuNpULMkfZydQ==", + "requires": { + "base64-js": "^1.3.0", + "core-js": "^2.6.4", + "crypto-js": "^3.1.9-1", + "uuid": "^3.3.2" + }, + "dependencies": { + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + } + } + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", diff --git a/package.json b/package.json index cc28ecc..cf2012d 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "element-ui": "^2.8.2", "font-awesome": "^4.7.0", "js-cookie": "^2.2.0", + "oidc-client": "^1.4.1", "v-charts": "^1.19.0", "vue": "^2.5.21", "vue-i18n": "^8.10.0", diff --git a/src/App.vue b/src/App.vue index 01fc8b6..678aec8 100644 --- a/src/App.vue +++ b/src/App.vue @@ -153,8 +153,12 @@ import ScrollPane from './components/ScrollPane' import {getUserByToken} from './api/api'; + import applicationUserManager from "./Auth/applicationusermanager"; + import userAuth from "./Auth/UserAuth"; + export default { components: {Sidebar, ScrollPane}, + mixins: [userAuth], data() { return { sysName: 'BlogAdmin', @@ -253,8 +257,14 @@ this.tagsList = []; this.routes = []; this.$store.commit("saveTagsData", ""); - _this.$router.push('/login'); - window.location.reload() + + if (global.IS_IDS4) { + applicationUserManager.logout(); + } else { + _this.$router.push('/login'); + window.location.reload() + } + }).catch(() => { }); @@ -421,7 +431,12 @@ }, watch: { // 对router进行监听,每当访问router时,对tags的进行修改 - $route(newValue) { + $route: async function(newValue, from) { + + if (global.IS_IDS4) { + await this.refreshUserInfo(); + } + this.setTags(newValue); const tags = this.$refs.tag @@ -482,7 +497,6 @@ position: relative; overflow: hidden; border: 1px solid #f0f0f0; - margin-bottom: 20px; background: #f0f0f0; } diff --git a/src/Auth/UserAuth.js b/src/Auth/UserAuth.js new file mode 100644 index 0000000..b73dc3c --- /dev/null +++ b/src/Auth/UserAuth.js @@ -0,0 +1,27 @@ +import applicationUserManager from "./applicationusermanager"; +const userAuth = { + data() { + return { + user: { + name: "", + isAuthenticated: false + } + }; + }, + methods: { + async refreshUserInfo() { + const user = await applicationUserManager.getUser(); + if (user) { + this.user.name = user.profile.name; + this.user.isAuthenticated = true; + } else { + this.user.name = ""; + this.user.isAuthenticated = false; + } + } + }, + async created() { + await this.refreshUserInfo(); + } +}; +export default userAuth; diff --git a/src/Auth/applicationusermanager.js b/src/Auth/applicationusermanager.js new file mode 100644 index 0000000..df23efb --- /dev/null +++ b/src/Auth/applicationusermanager.js @@ -0,0 +1,26 @@ +import { UserManager } from 'oidc-client' + +class ApplicationUserManager extends UserManager { + constructor () { + super({ + authority: 'https://ids.neters.club', + client_id: 'blogadminjs', + redirect_uri: 'http://vueadmin.neters.club/callback', + response_type: 'id_token token', + scope: 'openid profile roles blog.core.api', + post_logout_redirect_uri: 'http://vueadmin.neters.club' + }) + } + + async login () { + await this.signinRedirect() + return this.getUser() + } + + async logout () { + return this.signoutRedirect() + } +} + +const applicationUserManager = new ApplicationUserManager() +export { applicationUserManager as default } diff --git a/src/api/api.js b/src/api/api.js index f6e8c88..795a0e7 100644 --- a/src/api/api.js +++ b/src/api/api.js @@ -4,6 +4,8 @@ import router from '../router/index' import store from "../store"; import Vue from 'vue'; +import applicationUserManager from "../Auth/applicationusermanager"; + let base = ''; // 如果是IIS部署,用这个,因为 IIS 只能是 CORS 跨域,不能代理 // let base = process.env.NODE_ENV=="production"? 'http://localhost:8081':''; @@ -64,14 +66,14 @@ axios.interceptors.response.use( type: 'success' }); - store.commit("saveToken", res.token); + store.commit("saveToken", res.response.token); var curTime = new Date(); - var expiredate = new Date(curTime.setSeconds(curTime.getSeconds() + res.expires_in)); + var expiredate = new Date(curTime.setSeconds(curTime.getSeconds() + res.response.expires_in)); store.commit("saveTokenExpire", expiredate); error.config.__isRetryRequest = true; - error.config.headers.Authorization = 'Bearer ' + res.token; + error.config.headers.Authorization = 'Bearer ' + res.response.token; return axios(error.config); } else { // 刷新token失败 清除token信息并跳转到登录页面 @@ -92,6 +94,14 @@ axios.interceptors.response.use( }); return null; } + // 429 ip限流 + if (error.response.status == 429) { + Vue.prototype.$message({ + message: '刷新次数过多,请稍事休息重试!', + type: 'error' + }); + return null; + } } return ""; // 返回接口返回的错误信息 } @@ -126,19 +136,25 @@ export const saveRefreshtime = params => { } }; const ToLogin = params => { + store.commit("saveToken", ""); store.commit("saveTokenExpire", ""); store.commit("saveTagsData", ""); window.localStorage.removeItem('user'); window.localStorage.removeItem('NavigationBar'); - router.replace({ - path: "/login", - query: {redirect: router.currentRoute.fullPath} - }); - - window.location.reload() - + + + if (global.IS_IDS4) { + applicationUserManager.login(); + } else { + router.replace({ + path: "/login", + query: {redirect: router.currentRoute.fullPath} + }); + + window.location.reload() + } }; export const getUserByToken = params => { @@ -272,3 +288,34 @@ export const getAccessApiByDate = params => { export const getAccessApiByHour = params => { return axios.get(`${base}/api/Monitor/GetAccessApiByHour`, {params: params}); }; +export const getServerInfo = params => { + return axios.get(`${base}/api/Monitor/Server`, {params: params}); +}; +export const getAccessLogs = params => { + return axios.get(`${base}/api/Monitor/GetAccessLogs`, {params: params}); +}; + + +// Task管理 +export const getTaskListPage = params => { + return axios.get(`${base}/api/TasksQz/get`, {params: params}); +}; +export const removeTask = params => { + return axios.delete(`${base}/api/TasksQz/delete`, {params: params}); +}; +export const editTask = params => { + return axios.put(`${base}/api/TasksQz/put`, params); +}; +export const addTask = params => { + return axios.post(`${base}/api/TasksQz/post`, params); +}; + +export const startJob = params => { + return axios.get(`${base}/api/TasksQz/StartJob`, {params: params}); +}; +export const stopJob = params => { + return axios.get(`${base}/api/TasksQz/StopJob`, {params: params}); +}; +export const reCovery = params => { + return axios.get(`${base}/api/TasksQz/ReCovery`, {params: params}); +}; \ No newline at end of file diff --git a/src/components/AppLink.vue b/src/components/AppLink.vue new file mode 100644 index 0000000..ca5fcb5 --- /dev/null +++ b/src/components/AppLink.vue @@ -0,0 +1,43 @@ + + + diff --git a/src/components/Sidebar.vue b/src/components/Sidebar.vue index 01d67e4..43fbb38 100644 --- a/src/components/Sidebar.vue +++ b/src/components/Sidebar.vue @@ -1,5 +1,6 @@ + + + - - - + + diff --git a/src/views/Blog/Blogs.vue b/src/views/Blog/Blogs.vue index e6dd709..79f9b48 100644 --- a/src/views/Blog/Blogs.vue +++ b/src/views/Blog/Blogs.vue @@ -1,22 +1,12 @@