当前位置: 首页 > news >正文

跨境电商网站开发技术wordpress固定导航

跨境电商网站开发技术,wordpress固定导航,宁波seo网络推广推荐,百度seoo优化软件完整项目地址#xff1a;vue-element-adminhttps://github.com/PanJiaChen/vue-element-admin前言拖更有点严重#xff0c;过了半个月才写了第二篇教程。无奈自己是一个业务猿#xff0c;每天被我司的产品虐的死去活来#xff0c;之前又病了一下休息了几天#xff0c;大家…完整项目地址vue-element-adminhttps://github.com/PanJiaChen/vue-element-admin前言拖更有点严重过了半个月才写了第二篇教程。无奈自己是一个业务猿每天被我司的产品虐的死去活来之前又病了一下休息了几天大家见谅。进入正题做后台项目区别于做其它的项目权限验证与安全性是非常重要的可以说是一个后台项目一开始就必须考虑和搭建的基础核心功能。我们所要做到的是不同的权限对应着不同的路由同时侧边栏也需根据不同的权限异步生成。这里先简单说一下我实现登录和权限验证的思路。登录当用户填写完账号和密码后向服务端验证是否正确验证通过之后服务端会返回一个token拿到token之后(我会将这个token存贮到cookie中保证刷新页面后能记住用户登录状态)前端会根据token再去拉取一个 user_info 的接口来获取用户的详细信息(如用户权限用户名等等信息)。权限验证通过token获取用户对应的 role动态根据用户的 role 算出其对应有权限的路由通过 router.addRoutes 动态挂载这些路由。上述所有的数据和操作都是通过vuex全局管理控制的。(补充说明刷新页面后 vuex的内容也会丢失所以需要重复上述的那些操作)接下来我们一起手摸手一步一步实现这个系统。登录篇首先我们不管什么权限来实现最基础的登录功能。随便找一个空白页面撸上两个input的框一个是登录账号一个是登录密码。再放置一个登录按钮。我们将登录按钮上绑上click事件点击登录之后向服务端提交账号和密码进行验证。 这就是一个最简单的登录页面。如果你觉得还要写的更加完美点你可以在向服务端提交之前对账号和密码做一次简单的校验。详细代码click事件触发登录操作:this.$store.dispatch(LoginByUsername, this.loginForm).then(() { this.$router.push({ path: / }); //登录成功之后重定向到首页}).catch(err { this.$message.error(err); //登录失败提示错误});复制代码action:LoginByUsername({ commit }, userInfo) { const username userInfo.username.trim() return new Promise((resolve, reject) { loginByUsername(username, userInfo.password).then(response { const data response.data Cookies.set(Token, response.data.token) //登录成功后将token存储在cookie之中 commit(SET_TOKEN, data.token) resolve() }).catch(error { reject(error) }); });}复制代码登录成功后服务端会返回一个 token(该token的是一个能唯一标示用户身份的一个key)之后我们将token存储在本地cookie之中这样下次打开页面或者刷新页面的时候能记住用户的登录状态不用再去登录页面重新登录了。ps:为了保证安全性我司现在后台所有token有效期(Expires/Max-Age)都是Session就是当浏览器关闭了就丢失了。重新打开浏览器都需要重新登录验证后端也会在每周固定一个时间点重新刷新token让后台用户全部重新登录一次确保后台用户不会因为电脑遗失或者其它原因被人随意使用账号。获取用户信息用户登录成功之后我们会在全局钩子router.beforeEach中拦截路由判断是否已获得token在获得token之后我们就要去获取用户的基本信息了//router.beforeEachif (store.getters.roles.length 0) { // 判断当前用户是否已拉取完user_info信息 store.dispatch(GetInfo).then(res { // 拉取user_info const roles res.data.role; next();//resolve 钩子 })复制代码就如前面所说的我只在本地存储了一个用户的token并没有存储别的用户信息(如用户权限用户名用户头像等)。有些人会问为什么不把一些其它的用户信息也存一下主要出于如下的考虑假设我把用户权限和用户名也存在了本地但我这时候用另一台电脑登录修改了自己的用户名之后再用这台存有之前用户信息的电脑登录它默认会去读取本地 cookie 中的名字并不会去拉去新的用户信息。所以现在的策略是页面会先从 cookie 中查看是否存有 token没有就走一遍上一部分的流程重新登录如果有token,就会把这个 token 返给后端去拉取user_info保证用户信息是最新的。 当然如果是做了单点登录得功能的话用户信息存储在本地也是可以的。当你一台电脑登录时另一台会被提下线所以总会重新登录获取最新的内容。而且从代码层面我建议还是把 login和get_user_info两件事分开比较好在这个后端全面微服务的年代后端同学也想写优雅的代码~权限篇先说一说我权限控制的主体思路前端会有一份路由表它表示了每一个路由可访问的权限。当用户登录之后通过 token 获取用户的 role 动态根据用户的 role 算出其对应有权限的路由再通过router.addRoutes动态挂载路由。但这些控制都只是页面级的说白了前端再怎么做权限控制都不是绝对安全的后端的权限验证是逃不掉的。我司现在就是前端来控制页面级的权限不同权限的用户显示不同的侧边栏和限制其所能进入的页面(也做了少许按钮级别的权限控制)后端则会验证每一个涉及请求的操作验证其是否有该操作的权限每一个后台的请求不管是 get 还是 post 都会让前端在请求 header里面携带用户的 token后端会根据该 token 来验证用户是否有权限执行该操作。若没有权限则抛出一个对应的状态码前端检测到该状态码做出相对应的操作。权限 前端or后端 来控制有很多人表示他们公司的路由表是于后端根据用户的权限动态生成的我司不采取这种方式的原因如下项目不断的迭代你会异常痛苦前端新开发一个页面还要让后端配一下路由和权限让我们想了曾经前后端不分离被后端支配的那段恐怖时间了。其次就拿我司的业务来说虽然后端的确也是有权限验证的但它的验证其实是针对业务来划分的比如超级编辑可以发布文章而实习编辑只能编辑文章不能发布但对于前端来说不管是超级编辑还是实习编辑都是有权限进入文章编辑页面的。所以前端和后端权限的划分是不太一致。还有一点是就vue2.2.0之前异步挂载路由是很麻烦的一件事不过好在官方也出了新的api虽然本意是来解决ssr的痛点的。。。addRoutes在之前通过后端动态返回前端路由一直很难做的因为vue-router必须是要vue在实例化之前就挂载上去的不太方便动态改变。不过好在vue2.2.0以后新增了router.addRoutesDynamically add more routes to the router. The argument must be an Array using the same route config format with the routes constructor option.有了这个我们就可相对方便的做权限控制了。(楼主之前在权限控制也走了不少歪路可以在项目的commit记录中看到重构了很多次最早没用addRoute整个权限控制代码里都是各种if/else的逻辑判断代码相当的耦合和复杂)具体实现创建vue实例的时候将vue-router挂载但这个时候vue-router挂载一些登录或者不用权限的公用的页面。当用户登录后获取用role将role和路由表每个页面的需要的权限作比较生成最终用户可访问的路由表。调用router.addRoutes(store.getters.addRouters)添加用户可访问的路由。使用vuex管理路由表根据vuex中可访问的路由渲染侧边栏组件。router.js首先我们实现router.js路由表这里就拿前端控制路由来举例(后端存储的也差不多稍微改造一下就好了)// router.jsimport Vue from vue;import Router from vue-router;import Login from ../views/login/;const dashboard resolve require([../views/dashboard/index], resolve);//使用了vue-routerd的[Lazy Loading Routes](https://router.vuejs.org/en/advanced/lazy-loading.html)//所有权限通用路由表 //如首页和登录页和一些不用权限的公用页面export const constantRouterMap [ { path: /login, component: Login }, { path: /, component: Layout, redirect: /dashboard, name: 首页, children: [{ path: dashboard, component: dashboard }] },]//实例化vue的时候只挂载constantRouterexport default new Router({ routes: constantRouterMap});//异步挂载的路由//动态需要根据权限加载的路由表 export const asyncRouterMap [ { path: /permission, component: Layout, name: 权限测试, meta: { role: [admin,super_editor] }, //页面需要的权限 children: [ { path: index, component: Permission, name: 权限测试页, meta: { role: [admin,super_editor] } //页面需要的权限 }] }, { path: *, redirect: /404, hidden: true }];复制代码这里我们根据 vue-router官方推荐 的方法通过meta标签来标示改页面能访问的权限有哪些。如meta: { role: [admin,super_editor] }表示该页面只有admin和超级编辑才能有资格进入。注意事项这里有一个需要非常注意的地方就是 404 页面一定要最后加载如果放在constantRouterMap一同声明了404后面的所以页面都会被拦截到404详细的问题见addRoutes when youve got a wildcard route for 404s does not workmain.js关键的main.js// main.jsrouter.beforeEach((to, from, next) { if (store.getters.token) { // 判断是否有token if (to.path /login) { next({ path: / }); } else { if (store.getters.roles.length 0) { // 判断当前用户是否已拉取完user_info信息 store.dispatch(GetInfo).then(res { // 拉取info const roles res.data.role; store.dispatch(GenerateRoutes, { roles }).then(() { // 生成可访问的路由表 router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表 next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record }) }).catch(err { console.log(err); }); } else { next() //当有用户权限的时候说明所有可访问路由已生成 如访问没权限的全面会自动进入404页面 } } } else { if (whiteList.indexOf(to.path) ! -1) { // 在免登录白名单直接进入 next(); } else { next(/login); // 否则全部重定向到登录页 } }});复制代码这里的router.beforeEach也结合了上一章讲的一些登录逻辑代码。 上面一张图就是在使用addRoutes方法之前的权限判断非常的繁琐因为我是把所有的路由都挂在了上去所有我要各种判断当前的用户是否有权限进入该页面各种if/else的嵌套维护起来相当的困难。但现在有了addRoutes之后就非常的方便我只挂载了用户有权限进入的页面没权限路由自动帮我跳转的404,省去了不少的判断。这里还有一个小hack的地方就是router.addRoutes之后的next()可能会失效因为可能next()的时候路由并没有完全add完成好在查阅文档发现next(/) or next({ path: / }): redirect to a different location. The current navigation will be aborted and a new one will be started.这样我们就可以简单的通过next(to)巧妙的避开之前的那个问题了。这行代码重新进入router.beforeEach这个钩子这时候再通过next()来释放钩子就能确保所有的路由都已经挂在完成了。store/permission.js就来就讲一讲 GenerateRoutes Action// store/permission.jsimport { asyncRouterMap, constantRouterMap } from src/router;function hasPermission(roles, route) { if (route.meta route.meta.role) { return roles.some(role route.meta.role.indexOf(role) 0) } else { return true }}const permission { state: { routers: constantRouterMap, addRouters: [] }, mutations: { SET_ROUTERS: (state, routers) { state.addRouters routers; state.routers constantRouterMap.concat(routers); } }, actions: { GenerateRoutes({ commit }, data) { return new Promise(resolve { const { roles } data; const accessedRouters asyncRouterMap.filter(v { if (roles.indexOf(admin) 0) return true; if (hasPermission(roles, v)) { if (v.children v.children.length 0) { v.children v.children.filter(child { if (hasPermission(roles, child)) { return child } return false; }); return v } else { return v } } return false; }); commit(SET_ROUTERS, accessedRouters); resolve(); }) } }};export default permission;复制代码这里的代码说白了就是干了一件事通过用户的权限和之前在router.js里面asyncRouterMap的每一个页面所需要的权限做匹配最后返回一个该用户能够访问路由有哪些。侧边栏最后一个涉及到权限的地方就是侧边栏不过在前面的基础上已经很方便就能实现动态显示侧边栏了。这里侧边栏基于element-ui的NavMenu来实现的。 代码有点多不贴详细的代码了有兴趣的可以直接去github上看地址或者直接看关于侧边栏的文档。说白了就是遍历之前算出来的permission_routers通过vuex拿到之后动态v-for渲染而已。不过这里因为有一些业务需求所以加了很多判断 比如我们在定义路由的时候会加很多参数/*** hidden: true if hidden:true will not show in the sidebar(default is false)* redirect: noredirect if redirect:noredirect will no redirct in the breadcrumb* name:router-name the name is used by (must set!!!)* meta : { role: [admin,editor] will control the page role (you can set multiple roles) title: title the name show in submenu and breadcrumb (recommend set) icon: svg-name the icon show in the sidebar, noCache: true if fasle ,the page will no be cached(default is false) }**/复制代码这里仅供参考而且本项目为了支持无限嵌套路由所有侧边栏这块使用了递归组件。如需要请大家自行改造来打造满足自己业务需求的侧边栏。侧边栏高亮问题:很多人在群里问为什么自己的侧边栏不能跟着自己的路由高亮其实很简单element-ui官方已经给了default-active所以我们只要:default-active$route.path 将default-active一直指向当前路由就可以了就是这么简单按钮级别权限控制有很多人一直在问关于按钮级别粒度的权限控制怎么做。我司现在是这样的真正需要按钮级别控制的地方不是很多现在是通过获取到用户的role之后在前端用v-if手动判断来区分不同权限对应的按钮的。理由前面也说了我司颗粒度的权限判断是交给后端来做的每个操作后端都会进行权限判断。而且我觉得其实前端真正需要按钮级别判断的地方不是很多如果一个页面有很多种不同权限的按钮我觉得更多的应该是考虑产品层面是否设计合理。当然你强行说我想做按钮级别的权限控制你也可以参照路由层面的做法搞一个操作权限表。。。但个人觉得有点多此一举。或者将它封装成一个指令都是可以的。axios拦截器这里再说一说 axios 吧。虽然在上一篇系列文章中简单介绍过不过这里还是要在唠叨一下。如上文所说我司服务端对每一个请求都会验证权限所以这里我们针对业务封装了一下请求。首先我们通过request拦截器在每个请求头里面塞入token好让后端对请求进行权限验证。并创建一个respone拦截器当服务端返回特殊的状态码我们统一做处理如没权限或者token失效等操作。import axios from axiosimport { Message } from element-uiimport store from /storeimport { getToken } from /utils/auth// 创建axios实例const service axios.create({ baseURL: process.env.BASE_API, // api的base_url timeout: 5000 // 请求超时时间})// request拦截器service.interceptors.request.use(config { // Do something before request is sent if (store.getters.token) { config.headers[X-Token] getToken() // 让每个请求携带token--[X-Token]为自定义key 请根据实际情况自行修改 } return config}, error { // Do something with request error console.log(error) // for debug Promise.reject(error)})// respone拦截器service.interceptors.response.use( response response, /** * 下面的注释为通过response自定义code来标示请求状态当code返回如下情况为权限有问题登出并返回到登录页 * 如通过xmlhttprequest 状态码标识 逻辑可写在下面error中 */ // const res response.data; // if (res.code ! 20000) { // Message({ // message: res.message, // type: error, // duration: 5 * 1000 // }); // // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了; // if (res.code 50008 || res.code 50012 || res.code 50014) { // MessageBox.confirm(你已被登出可以取消继续留在该页面或者重新登录, 确定登出, { // confirmButtonText: 重新登录, // cancelButtonText: 取消, // type: warning // }).then(() { // store.dispatch(FedLogOut).then(() { // location.reload();// 为了重新实例化vue-router对象 避免bug // }); // }) // } // return Promise.reject(error); // } else { // return response.data; // } error { console.log(err error)// for debug Message({ message: error.message, type: error, duration: 5 * 1000 }) return Promise.reject(error) })export default service复制代码两步验证文章一开始也说了后台的安全性是很重要的简简单单的一个账号密码的方式是很难保证安全性的。所以我司的后台项目都是用了两步验证的方式之前我们也尝试过使用基于 google-authenticator 或者youbikey这样的方式但难度和操作成本都比较大。后来还是准备借助腾讯爸爸这年代谁不用微信。。。安全性腾讯爸爸也帮我做好了保障。 楼主建议两步验证要支持多个渠道不要只微信或者QQ前段时间QQ第三方登录就出了bug官方两三天才修好的害我背了锅/(ㄒoㄒ)/~~ 。这里的两部验证有点名不副实其实就是账号密码验证过之后还需要一个绑定的第三方平台登录验证而已。 写起来也很简单在原有登录得逻辑上改造一下就好。this.$store.dispatch(LoginByEmail, this.loginForm).then(() { //this.$router.push({ path: / }); //不重定向到首页 this.showDialog true //弹出选择第三方平台的dialog}).catch(err { this.$message.error(err); //登录失败提示错误});复制代码登录成功之后不直接跳到首页而是让用户两步登录选择登录得平台。 接下来就是所有第三方登录一样的地方通过 OAuth2.0 授权。这个各大平台大同小异大家自行查阅文档不展开了就说一个微信授权比较坑的地方。注意你连参数的顺序都不能换不然会验证不通过。具体代码同时我也封装了openWindow方法大家自行看吧。 当第三方授权成功之后都会跳到一个你之前有一个传入redirect——uri的页面 如微信还必须是你授权账号的一级域名。所以你授权的域名是vue-element-admin.com,你就必须重定向到vue-element-admin.com/xxx/下面所以你需要写一个重定向的服务如vue-element-admin.com/auth/redirect?a.com 跳到该页面时会再次重定向给a.com。所以我们后台也需要开一个authredirect页面代码。他的作用是第三方登录成功之后会默认跳到授权的页面授权的页面会再次重定向回我们的后台由于是spa改变路由的体验不好我们通过window.opener.location.href的方式改变hash在login.js里面再监听hash的变化。当hash变化时获取之前第三方登录成功返回的code与第一步账号密码登录之后返回的uid一同发送给服务端验证是否正确如果正确这时候就是真正的登录成功。 created() { window.addEventListener(hashchange, this.afterQRScan); }, destroyed() { window.removeEventListener(hashchange, this.afterQRScan); }, afterQRScan() { const hash window.location.hash.slice(1); const hashObj getQueryObject(hash); const originUrl window.location.origin; history.replaceState({}, , originUrl); const codeMap { wechat: code, tencent: code }; const codeName hashObj[codeMap[this.auth_type]]; this.$store.dispatch(LoginByThirdparty, codeName).then(() { this.$router.push({ path: / }); }); }复制代码到这里涉及登录权限的东西也差不多讲完了这里楼主只是给了大家一个实现的思路(都是楼主不断摸索的血泪史)每个公司实现的方案都有些出入请谨慎选择适合自己业务形态的解决方案。如果有什么想法或者建议欢迎去本项目下留言一同讨论。
http://www.pierceye.com/news/803133/

相关文章:

  • 百度怎么把自己网站展现在百度森动网网站建设好吗
  • 城市生活网官方网站app成都设计院
  • 移动网站开发实训报告清远企业网站建设
  • 手机版网站如何做陕西城乡建设网站
  • 大连网站建设事件营销的特点
  • 做语音聊天网站要多少钱app界面设计模板素材免费
  • 设计网站专题页包括那些项目个人做网站要买什么域名
  • 建网站 方法中信建设有限责任公司获奖
  • 做宠物商品的网站无锡自适应网站开发
  • 网站后台怎样登陆做网站数据库及相关配置
  • 昆明seo网站排名网站代码 输入文字 跳出内容
  • 济南建站公司网站广州市网站设计
  • 网站模板做的比较好的公司网站制作汇报会
  • 个人网站图片海外网站备案
  • 兰州手机网站制作公司哪家好网店分销平台
  • 百度建立自己的网站网络工程师培训课程
  • 微网站的制作过程海南注册公司怎么注册
  • 公司网站制作投标建站行业都扁平化设计
  • 男女做a视频网站wordpress询价功能
  • 网站建设视频百度网盘下载我做网站价格
  • 江苏省建设集团有限公司网站首页东莞网络推广外包
  • 梁平网站建设莱芜网络营销
  • 自学网站建设需要什么学历学校网站建设总结报告
  • 增城新塘网站建设平面设计技术培训机构
  • 游戏网站开发视频运动品牌网页设计
  • 成都比较好的网站建设公司做视频后期的网站
  • 重庆网页搜索排名提升专业seo优化推广
  • 手机免费代理ip网站模板网站的优势有哪些
  • dede地方门户网站模板做网站备案
  • 域名访问网站的知识站酷网官网进入