mall4cloud 开源项目源码阅读

目录

项目搭建:

前端mall4cloud-platform-master:

需求:

技术

 开发环境跨域解决

代码实现:

后端:

设计思路:

token授权服务:

用户权限服务:

代码实现

总结 :


项目搭建:

        微服务商城 商城源码 分布式商城-商城系统: ⭐️⭐️⭐️Mall4cloud微服商城系统、SpringCloud微服商城系统、B2C微服商城、BBC微服商城、saas商城、SBC商城、微服商城源码、分销微服商城、H5商城、APP商城、PC商城、微服商城、积分商城、会员商城、秒杀商城、团购商城、商城源码、多店商城、供应链商城、多语言商城、商城系统、多用户商城、springboot3商城 (gitee.com)

        根据官方文档

前端mall4cloud-platform-master:

需求:

        用户登录成功跳转到用户界面,token过期跳转到登录页面,后端配置用户的权限页面

技术

        vuex状态管理: 简单的理解就是一个全局的数据存储。

        路由: 你配置了路径,view就可以转到你想要去的页面。

        路由守卫:页面跳转的时候,可以做一个拦截的作用。

        基本实现思路:用户登录的时候保存一个token到store里面,跳转到首页, 每一次页面跳转的时候路由守卫就检测,是否有token,是否有权限。

        

 开发环境跨域解决

        vue.config.js开启代理。

        

  devServer: {
    proxy:{
        
      '/dycloud-auth':{  //请求的api 例如请求是 http://localhost:8080/dycloud-rbac/role/page
        target:"http://localhost:8000", // 网关地址
        ws:true,
        changeOrigin:true
      },
      '/dycloud-platform':{
        target:"http://localhost:8000",
        ws:true,
        changeOrigin:true
      },
      '/dycloud-rbac':{
        target:"http://localhost:8000",
        ws:true,
        changeOrigin:true
      },

    }
  },

代码实现:

        

        点击登录按钮的时候

    login(verifyResult) {
      console.log(verifyResult.captchaVerification)
      this.loading = true
      this.loginInfo.captcha = verifyResult.captchaVerification
      
       调用store login动作 login里面又请求了登录接口,并且将token保存到store
      this.$store.dispatch('user/login', this.loginInfo)
        .then(() => {
          重定向
          this.$router.push({ path: this.redirect || '/', query: this.otherQuery })
          this.loading = false
        })
        .catch((e) => {
          console.log(e)
          this.loading = false
        })
    },

        发出重定向指令的时候会先去路由守卫判断。

    如果存在token
  if (hasToken) {
    console.log("路径")
    console.log(to.path)
    如果当前页面是login 也就是你点击的是登录页
    if (to.path === '/login') {
      // 放行到主页
      next({ path: '/' })
      NProgress.done() // hack: https://github.com/PanJiaChen/vue-element-admin/pull/2939
    } else {
      // debugger
      // determine whether the user has obtained his permission roles through getInfo
      如果有角色直接放行
      if (hasRoles) {
        next()
      } else {
           
        try {
          // 调用后端接口 获取用户信息 和权限,保存到store里面
          const userInfo = await store.dispatch('user/getUserInfo')
          // 获取权限信息
        
          store.dispatch('user/listPermissions')

          let menuIds = []

          if (!userInfo.isAdmin) {
            // 获取菜单信息
            menuIds = await store.dispatch('user/listMenuIds')
          }

          // 获取当前用户的菜单列表
          const accessRoutes = await store.dispatch('permission/generateRoutes', menuIds)
          // 404页面放入路由
          accessRoutes.push({ path: '*', redirect: '/404', hidden: true })
          // 将后端配置的路由放入路由
          router.addRoutes(accessRoutes)

          放行
          next({ ...to, replace: true })
        } catch (error) {
          // remove token and go to login page to re-login
          await store.dispatch('user/resetToken')
          next(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      }
    }
  } 

注意点:用户首次登录只设置了token,没有角色。所以此时一定会执行到else里面,去查询角色,菜单权限。

        store里面的数据也是响应双向的。

下面是store代码

        

  login({ commit }, userInfo) {
    const { username, password, captcha } = userInfo
    return new Promise((resolve, reject) => {
      login({ principal: username.trim(), credentials: password, captchaVerification: captcha, sysType: 2 }).then(response => {
        commit('SET_TOKEN', response.accessToken)
        setToken(response.accessToken)
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  // get permissions
  listPermissions({ commit, state }) {
    return new Promise((resolve, reject) => {
      if (state.isAdmin) {
        commit('SET_ROLES', [''])
        resolve([''])
        return
      }
      menuPermissionsList().then(permissions => {
        console.log(permissions)
        if (!permissions) {
          reject('Verification failed, please Login again.')
        }

        // roles must be a non-empty array
        if (!permissions || permissions.length <= 0) {
          permissions = ['']
        }
        commit('SET_ROLES', permissions)
        resolve(permissions)
      }).catch(error => {
        reject(error)
      })
    })
  },

后端:

        权限校验过程,在commom,security  AuthFilter下面。

设计思路:

        用户先请求一个登录接口:获取token,并且token和用户信息绑定。

        后面每一次请求,都去查看一下token,和用户权限有没有问题。

        所以需要检测token的接口,和用户权限的接口.

        硬件方面看。首先经过网关服务器,请求到登录接口获取到token。此时前端拿到token了,前端后续请求,因为不确定客户端要请求哪一个服务,所有做一个公共的拦截器,去检测token和权限问题。

        做一个sverlet拦截器。

                定义服务器内部feign请求都是以 /feign开始

                定义白名单ip

                定义无须拦截的请求地址 登录接口就无需拦截

       实现思路:

首先需要定义token,和权限检测接口。具体实现交给其他服务。

                1.验证http请求,uri,如果是feign请求,则验证key, secret凭证(就是验证服务器保存一份,其他服务器请求的时候放在header里面,再进行一下对比)

                2.查看设置的白名单,如果有白名单则,则验证请求是否在白名单里面。

        上述验证未通过,则抛出异常。

                3.如果是检测token的请求,则放行。

                4.放行配置中无需权限校验的uri

                5.token校验 token和用户信息需要绑定,调用token接口

                6.用户权限校验 调用权限接口

                7.为了便于在控制器里面获取用户信息,使用ThreadLocal保存起来

                8.整个http结束,清除token信息。

token授权服务:

        首先是登录,去数据库里面查用户信息。

        生成一个token 用uuid就行

        然后建立token 和用户信息的关系,存储到redis中,redis可以设置过期时间,所以token的过期时间也解决了。

        token加密返回给前端。

        

        token校验:

                我们是一个微服务,所以每一http,其他服务器都会请求授权服务校验一下token。

                所以是一个feign接口,公共包也定义了这个请求。

                校验过程就很简单了,登录已经录入了数据,校验再根据token取数据就行了。

用户权限服务:

        用户,角色,权限,菜单。管理项目,和token校验一样是单独的一个服务。

       

代码实现

        公共包下面定义一个权限包,做http拦截,以后那个项目需要权限引入就行。

        

        

api中定义,权限的接口。检查token,检查权限。 由具体的服务去实现,只定义标准。所以以后想换一个认证服务,权限管理服务,也很简单。

        

                接口具体的实现

        

总结 :

        前端:登录再进入菜单,整个流程是怎么样子的。涉及到的技术,请求,状态管理,路由拦截,路由。

        后端:token是怎么生成的?每一次请求是怎么校验token,权限的?。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值