住房和城乡建设主管部门网站宝塔 wordpress 规则

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

住房和城乡建设主管部门网站,宝塔 wordpress 规则,一个旅游网站建设,百度推广个人能开户吗若依框架登录鉴权#xff1a;1.获取token#xff08;过期在响应拦截器中实现#xff09;,2.基于RBAC模型获取用户、角色和权限信息#xff08;在路由前置守卫#xff09;#xff0c;3.根据用户权限动态生成#xff08;从字符串-组件#xff0c;根据permission添加动… 若依框架登录鉴权1.获取token过期在响应拦截器中实现,2.基于RBAC模型获取用户、角色和权限信息在路由前置守卫3.根据用户权限动态生成从字符串-组件根据permission添加动态路由信息和添加路由addRoutes在路由前置守卫 若依框架Ruoyi后端的登录权限身份认证流程是一个复杂但高效的过程它确保了系统的安全性和数据的保护。以下是一个典型的若依框架后端登录权限身份认证流程基于多个来源的信息进行归纳和整理 1.发起请求获取认证凭证token 现象用户未登录或者token过期刷新页面将重定向至登录页面 如果用户身份验证通过系统会生成一个认证凭证如JWT即JSON Web Token。 认证凭证的生成过程可能包括生成一个唯一的UUID作为token的一部分并设置token的有效期这个有效期可能是通过Redis等缓存系统来控制的因为JWT本身不直接支持自动刷新有效期。生成的token会包含用户的基本信息和权限信息以便后续进行权限控制和身份验证。后端通过验证后返回一个包含用户信息的令牌Token前端将这个令牌保存起来如存储在Cookie、LocalStorage或SessionStorage中以后的请求都需要带上这个令牌进行验证。 ​ //login.vue handleLogin() {this.\(refs.loginForm.validate(valid {if (valid) {this.loading true;if (this.loginForm.rememberMe) {Cookies.set(username, this.loginForm.username, { expires: 30 });Cookies.set(password, encrypt(this.loginForm.password), { expires: 30 });Cookies.set(rememberMe, this.loginForm.rememberMe, { expires: 30 });} else {Cookies.remove(username);Cookies.remove(password);Cookies.remove(rememberMe);}this.\)store.dispatch(Login, this.loginForm).then(() {//存储title至vuexthis.\(store.commit(settings/SET_HEADTITLE,this.title)this.\)router.push({ path: this.redirect || / }).catch((){});}).catch(() {this.loading false;if (this.captchaEnabled) {this.getCode();}});}});} //store/modules/user.js // 前端登录请求Login({ commit }, userInfo) {const username userInfo.username.trim()const password userInfo.passwordconst code userInfo.codeconst uuid userInfo.uuidreturn new Promise((resolve, reject) {login(username, password, code, uuid).then(res {//key//获取并设置后端传过来的tokensetToken(res.data.token)commit(SET_TOKEN, res.data.token)resolve()}).catch(error {reject(error)})})}, //system/SysLoginController //后端登录响应/*** 登录方法** param loginBody 登录信息* return 结果*/SaIgnorePostMapping(/login)public RMapString, Object login(Validated RequestBody LoginBody loginBody) {MapString, Object ajax new HashMap();// 生成令牌String token loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),loginBody.getUuid());ajax.put(Constants.TOKEN, token);return R.ok(ajax);}​ 若依框架前端怎样判断token是否过期并且要重新登录获取token响应拦截器 在前端应用中使用响应拦截器response interceptor来判断token是否过期并在需要时重新登录以获取新的token是一种常见的做法。这通常涉及到以下几个步骤 设置响应拦截器在发起HTTP请求的库如axios中设置拦截器以便在接收到响应时执行自定义逻辑。 检查响应状态码在拦截器中检查响应的状态码特别是那些表明需要身份验证的状态码如401、403等。 判断token是否过期虽然401状态码通常表示未授权但具体是否因为token过期导致需要额外的逻辑来判断。有时候后端会在响应头中返回一个特定的字段如WWW-Authenticate来指示这一点但更常见的是通过解析响应体中的信息如错误信息来判断。不过在某些情况下你可能只是简单地根据收到了401就认为token已过期。 重新登录获取token如果确定token已过期你可以尝试使用某种形式的“刷新token”来自动获取新的access token或者引导用户重新登录。这取决于你的应用是否支持无感知重新登录使用refresh token以及后端的实现。 更新本地存储和重试请求如果成功获取了新的token更新本地存储中的token并根据需要重试之前的请求。 错误处理处理在重新登录过程中可能出现的任何错误并向用户显示适当的反馈。
//utils/request.js // 响应拦截器 service.interceptors.response.use(res {// 未设置状态码则默认成功状态const code res.data.code || 200;// 获取错误信息const msg errorCode[code] || res.data.msg || errorCode[default]// 二进制数据则直接返回if (res.request.responseType blob || res.request.responseType arraybuffer) {return res.data}if (code 401) {if (!isRelogin.show) {isRelogin.show true;MessageBox.confirm(登录状态已过期您可以继续留在该页面或者重新登录, 系统提示, { confirmButtonText: 重新登录, cancelButtonText: 取消, type: warning }).then(() {isRelogin.show false;store.dispatch(LogOut).then(() {location.href process.env.VUE_APP_CONTEXT_PATH index;})}).catch(() {isRelogin.show false;});}return Promise.reject(无效的会话或者会话已过期请重新登录。)}// else if (code 500) {// Message({ message: msg, type: error })//redis错误待解决// return Promise.reject(new Error(msg))// }else if (code 601) {Message({ message: msg, type: warning })return Promise.reject(error)} else if (code ! 200) {Notification.error({ title: msg })return Promise.reject(error)} else {return res.data}},error {console.log(err error)let { message } error;if (message Network Error) {message 后端接口连接异常;} else if (message.includes(timeout)) {message 系统接口请求超时;} else if (message.includes(Request failed with status code)) {message 系统接口 message.substr(message.length - 3) 异常;}Message({ message: message, type: error, duration: 5 * 1000 })return Promise.reject(error)} )若报401错误表明token到期401错误是一种常见的HTTP状态码它表示“未授权”Unauthorized访问。当用户尝试访问受保护的资源时如果未能提供有效的身份验证信息或提供的身份验证信息被拒绝服务器就会返回401错误。这种错误通常出现在需要登录或授权才能访问的网站上如银行网站、社交媒体网站等。 2. 获取认证信息user、roles and permission 不同用户的权限不同右侧导航条【大层面】和页面中操作按钮【小层面】不同 将生成的token和用户的相关信息如用户ID、角色、权限等缓存起来以便后续快速验证和查询。 //store/modules/user.js// 获取用户信息【前端请求】GetInfo({ commit, state }) {return new Promise((resolve, reject) {getInfo().then(res {const user res.data.userconst avatar (user.avatar || user.avatar null) ? require(/assets/images/profile.jpg) : user.avatar;if (res.data.roles res.data.roles.length 0) { // 验证返回的roles是否是一个非空数组commit(SET_ROLES, res.data.roles)commit(SET_PERMISSIONS, res.data.permissions)} else {commit(SET_ROLES, [ROLE_DEFAULT])}commit(SET_NAME, user.userName)commit(SET_AVATAR, avatar)resolve(res)}).catch(error {reject(error)})})},//system/SysLoginController //后端响应返回用户信息【user、roles and permisssions】/*** 获取用户信息** return 用户信息/GetMapping(getInfo)public RMapString, Object getInfo() {LoginUser loginUser LoginHelper.getLoginUser();SysUser user userService.selectUserById(loginUser.getUserId());MapString, Object ajax new HashMap();ajax.put(user, user);ajax.put(roles, loginUser.getRolePermission());ajax.put(permissions, loginUser.getMenuPermission());return R.ok(ajax);} 管理员  普通员工 根据权限动态生成并添加路由 步骤 1: 定义静态路由和异步路由 首先你需要定义你的路由通常分为静态路由不需要权限即可访问的路由如登录页、404页面等和异步路由需要权限的路由如用户管理、订单管理等。 /** Note: 路由配置项** hidden: true // 当设置 true 的时候该路由不会再侧边栏出现 如401login等页面或者如一些编辑页面/edit/1* alwaysShow: true // 当你一个路由下面的 children 声明的路由大于1个时自动会变成嵌套的模式–如组件页面* // 只有一个时会将那个子路由当做根路由显示在侧边栏–如引导页面* // 若你想不管路由下面的 children 声明的个数都显示你的根路由* // 你可以设置 alwaysShow: true这样它就会忽略之前定义的规则一直显示根路由* redirect: noRedirect // 当设置 noRedirect 的时候该路由在面包屑导航中不可被点击* name:router-name // 设定路由的名字一定要填写不然使用keep-alive时会出现各种问题* query: {id: 1, name: ry} // 访问路由的默认传递参数* roles: [admin, common] // 访问路由的角色权限* permissions: [a:a:a, b:b:b] // 访问路由的菜单权限* meta : {noCache: true // 如果设置为true则不会被 keep-alive 缓存(默认 false)title: title // 设置该路由在侧边栏和面包屑中展示的名字icon: svg-name // 设置该路由的图标对应路径src/assets/icons/svgbreadcrumb: false // 如果设置为false则不会在breadcrumb面包屑中显示activeMenu: /system/user // 当路由设置了该属性则会高亮相对应的侧边栏。}/ // router/index.js import Vue from vue
import Router from vue-router Vue.use(Router) // 静态路由
const constantRoutes [ { path: /login, component: () import(/views/login/index), hidden: true }, { path: /404, component: () import(/views/404), hidden: true }
] // 异步路由示例
const asyncRoutes [ { path: /user, component: () import(/views/user/index), meta: { title: 用户管理, roles: [admin, editor] } }, // 更多路由…
] const createRouter () new Router({ // mode: history, // 需要后端支持 scrollBehavior: () ({ y: 0 }), routes: constantRoutes
}) const router createRouter() // 动态添加路由
function addAsyncRoutes(routes) { routes.forEach(route { router.addRoute(route) })
} export { router, addAsyncRoutes, asyncRoutes
} 步骤 2:  路由守卫与权限验证和路由添加 在用户登录后你需要从后端获取用户的权限信息并根据这些权限信息来过滤和添加路由。 你还需要设置路由守卫来确保用户在没有权限时不能访问某些页面。 //src/permission.js //前端路由守卫 router.beforeEach((to, from, next) {NProgress.start()if (getToken()) {//获取路由的mata.title属性并存储在Vuex中to.meta.title store.dispatch(settings/setTitle, to.meta.title)/
has token*/if (to.path /login) {next({ path: / })NProgress.done()} else {if (store.getters.roles.length 0) {isRelogin.show true// 判断当前用户是否已拉取完user_info信息store.dispatch(GetInfo).then(() {isRelogin.show false//生成路由store.dispatch(GenerateRoutes).then(accessRoutes {// 根据roles权限生成可访问的路由表//添加路由router.addRoutes(accessRoutes) // 动态添加可访问路由表next({ …to, replace: true }) // hack方法 确保addRoutes已完成})}).catch(err {store.dispatch(LogOut).then(() {Message.error(err)next({ path: / })})})} else {next()}}} else {// 没有tokenif (whiteList.indexOf(to.path) ! -1) {// 在免登录白名单直接进入next()} else {next(/login?redirect\({to.fullPath}) // 否则全部重定向到登录页NProgress.done()}} })获取与添加**路由**      //生成路由store.dispatch(GenerateRoutes).then(accessRoutes {// 根据roles权限生成可访问的路由表//添加路由router.addRoutes(accessRoutes) // 动态添加可访问路由表next({ ...to, replace: true }) // hack方法 确保addRoutes已完成}) GenerateRoutes 请求得到的sdata与rdata //store/module/permisssion.js// 生成路由GenerateRoutes({ commit }) {return new Promise(resolve {// 向后端请求路由数据getRouters().then(res {const sdata JSON.parse(JSON.stringify(res.data))const rdata JSON.parse(JSON.stringify(res.data))//console.log(sdata,rdata); //arrayconst sidebarRoutes filterAsyncRouter(sdata)const rewriteRoutes filterAsyncRouter(rdata, false, true)// 动态路由基于用户权限动态去加载const asyncRoutes filterDynamicRoutes(dynamicRoutes);rewriteRoutes.push({ path: *, redirect: /404, hidden: true })router.addRoutes(asyncRoutes);commit(SET_ROUTES, rewriteRoutes)commit(SET_SIDEBAR_ROUTERS, constantRoutes.concat(sidebarRoutes))commit(SET_DEFAULT_ROUTES, sidebarRoutes)commit(SET_TOPBAR_ROUTES, sidebarRoutes)resolve(rewriteRoutes)})})}// 遍历后台传来的路由字符串转换为组件对象 function filterAsyncRouter(asyncRouterMap, lastRouter false, type false) {return asyncRouterMap.filter(route {//type标识sidebarRoutesfalse)与rewriteRoutestrueif (type route.children) {route.children filterChildren(route.children)}if (route.component) {// Layout ParentView 组件特殊处理if (route.component Layout) {route.component Layout} else if (route.component ParentView) {route.component ParentView} else if (route.component InnerLink) {route.component InnerLink} else {//指定目录下找对应组件route.component loadView(route.component)}}if (route.children ! null route.children route.children.length) {//递归route.children filterAsyncRouter(route.children, route, type)} else {delete route[children]delete route[redirect]}return true}) }function filterChildren(childrenMap, lastRouter false) {var children []childrenMap.forEach((el, index) {if (el.children el.children.length) {if (el.component ParentView !lastRouter) {el.children.forEach(c {c.path el.path / c.pathif (c.children c.children.length) {children children.concat(filterChildren(c.children, c))return}children.push(c)})return}}if (lastRouter) {el.path lastRouter.path / el.path}children children.concat(el)})return children }export const loadView (view) {if (process.env.NODE_ENV development) {return (resolve) require([/views/\){view}], resolve)} else {// 使用 import 实现生产环境的路由懒加载return () import(/views/${view})} } //权限判断 //store/modules/permission.js// 动态路由遍历验证是否具备权限export function filterDynamicRoutes(routes) {const res []routes.forEach(route {if (route.permissions) {if (auth.hasPermiOr(route.permissions)) {res.push(route)}} else if (route.roles) {if (auth.hasRoleOr(route.roles)) {res.push(route)}}})return res }//plugins/auth.jsimport store from /storefunction authPermission(permission) {const all_permission ::*;const permissions store.getters store.getters.permissionsif (permission permission.length 0) {return permissions.some(v {return all_permission v || v permission})} else {return false} }function authRole(role) {const super_admin admin;const roles store.getters store.getters.rolesif (role role.length 0) {return roles.some(v {return super_admin v || v role})} else {return false} }export default {// 验证用户是否具备某权限hasPermi(permission) {return authPermission(permission);},// 验证用户是否含有指定权限只需包含其中一个hasPermiOr(permissions) {return permissions.some(item {return authPermission(item)})},// 验证用户是否含有指定权限必须全部拥有hasPermiAnd(permissions) {return permissions.every(item {return authPermission(item)})},// 验证用户是否具备某角色hasRole(role) {return authRole(role);},// 验证用户是否含有指定角色只需包含其中一个hasRoleOr(roles) {return roles.some(item {return authRole(item)})},// 验证用户是否含有指定角色必须全部拥有hasRoleAnd(roles) {return roles.every(item {return authRole(item)})} }addRoute router.addRoutes(accessRoutes) // 动态添加可访问路由表next({ …to, replace: true }) // hack方法 确保addRoutes已完成 第一行router.addRoutes(accessRoutes) 这行代码的作用是动态地向Vue Router的路由表中添加路由。addRoutes方法是Vue Router早期版本Vue Router 2.x中用于动态添加路由的方法。然而需要注意的是在Vue Router 3.x及更高版本中官方推荐使用addRoutes的替代方案即通过router.matcher.addRoutes或者完全重新创建router实例来动态添加路由因为addRoutes方法在Vue Router 4.x中被移除。但这里我们仍然以addRoutes为例进行说明。 router这是Vue Router的实例它包含了应用的所有路由配置。addRoutes这是Vue Router实例上的一个方法用于向路由表中添加新的路由规则。accessRoutes这是一个数组包含了要添加到路由表中的路由对象。每个路由对象都遵循Vue Router的路由配置规范包括path、component、children等属性。 第二行next({ …to, replace: true }) 这行代码通常出现在Vue Router的导航守卫Navigation Guards中用于控制路由的跳转。next函数是导航守卫的回调函数它决定了路由跳转的行为。 next这是一个必须调用的函数用于解决守卫中的钩子。调用它时可以传入一个位置对象或者一个错误。如果不调用则整个路由导航都将被“挂起”。{ …to, replace: true }这里使用了对象展开语法…来复制to对象的所有属性到一个新对象中并添加或修改replace属性为true。to对象通常包含了即将要跳转到的路由信息如path、query等。 replace: true这个选项的作用是当使用next函数进行路由跳转时不是将新路由添加到历史记录堆栈中而是替换掉当前的路由。这通常用于避免在路由跳转后留下无法退回到当前路由的“死胡同”。 结合使用这两行代码的场景 在实际应用中这两行代码经常一起使用在基于用户权限的路由控制中。比如当用户登录后后端返回了用户的权限信息前端根据这些权限信息动态生成可访问的路由表accessRoutes并通过router.addRoutes(accessRoutes)将这些路由添加到路由表中。然后在导航守卫中使用next({ …to, replace: true })来确保用户被重定向到目标路由并且由于replace: true这个跳转不会在历史记录中留下当前路由的入口从而避免了用户通过浏览器的前进/后退按钮访问到未授权的路由。 使用路由守卫保证addRoute执行完成你可以设置一个全局前置守卫beforeEach或后置守卫afterEach并在其中检查路由是否已经存在于路由表中。然而这种方法比较复杂且可能不够直观因为它依赖于路由守卫的多次调用和状态检查。 根据权限限制页面的操作按钮新增、修改和删除操作等