vue2 按钮权限控制组件 Authority

文章介绍了如何使用Vue的插槽功能,结合`hasPermission`计算属性,实现根据角色和权限动态显示或隐藏内容的组件。示例中详细展示了管理员和普通用户的不同权限场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注意:核心思想是使用插槽的方式,控制显示隐藏

第一步,创建一个名为Authority.vue的文件,并编写以下代码:

<template>
  <div>
    <slot v-if="hasPermission">{{ $slots.default }}</slot>
  </div>
</template>

<script>
export default {
  props: {
    role: {
      type: String,
      default: ''
    },
    permissions: {
      type: Array,
      default: () => []
    },
    permission: {
      type: String,
      default: ''
    }
  },
  computed: {
    hasPermission() {
      // 根据角色和权限判断是否有权限
      if (this.role === 'admin') {
        return true; // 管理员拥有所有权限
      }
      return this.permissions.includes(this.permission);
    }
  }
};
</script>

这里使用了插槽来显示具有权限的内容。hasPermission属性根据传入的角色和权限数据决定是否显示插槽内容。

然后,在使用该组件的地方,可以按照以下方式进行使用:

<template>
  <div>
    <authority :role="'admin'">
      <button>管理员才能看到的按钮</button>
    </authority>
    
    <authority
      :role="'user'"
      :permissions="['view:user']"
      :permission="'view:user'"
    >
      <div>普通用户只有在拥有查看用户权限时才能看到的内容</div>
    </authority>
    
    <authority
      :role="'user'"
      :permissions="['edit:user']"
      :permission="'view:user'"
    >
      <div>普通用户只有在拥有编辑用户权限时才能看到的内容</div>
    </authority>
  </div>
</template>

<script>
import Authority from '@/components/Authority.vue';

export default {
  components: {
    Authority
  }
};
</script>

这里展示了三个使用场景,其中第一个authority组件中,传入role='admin',表示只有管理员可以看到插槽中的内容,因此按钮会被显示。第二个和第三个authority组件中,传入role='user',表示是普通用户,但是在拥有view:useredit:user权限时,才能看到插槽中的内容。

通过这种方式,你可以灵活地根据具体情况来进行组合和使用,来实现更丰富的权限控制逻辑。

<think>嗯,用户问的是如何在前后端分离项目中用RBAC、Spring Security和Vue实现接口级的权限控制。首先,我得回忆一下RBAC的基本结构,角色、权限、用户之间的关系。然后,Spring Security这边,可能需要用到方法级别的安全控制,比如@PreAuthorize注解。Vue前端需要动态路由和按钮权限的控制。 首先,后端部分。用户权限数据应该怎么存?可能需要五张表:用户、角色、权限、用户角色关联、角色权限关联。Spring Security需要配置权限的加载方式,可能是从数据库查询用户的角色和权限,然后存到UserDetails里。这里要注意,用户登录后,每次请求都要携带JWT,后端需要解析JWT获取用户信息,然后根据权限判断是否有访问接口的权限。 然后是接口级别的控制,可能需要用Spring Security的全局方法安全,开启@PreAuthorize,用hasAuthority或者hasRole来注解各个接口。例如在Controller的方法上加@PreAuthorize("hasAuthority('user:add')")。这里可能需要自定义权限校验,比如有些复杂的逻辑,可以自定义PermissionEvaluator。 接下来是前端部分。Vue需要根据用户的权限动态生成路由,比如用addRoutes方法,过滤掉没有权限的路由。按钮级别的控制可以用v-if或者自定义指令,比如v-permission。用户登录后,后端需要返回权限列表,前端保存到Vuex或者Pinia里,然后在路由守卫里判断权限,动态加载路由。 需要考虑前后端的配合,比如权限的标识符怎么定义,保持一致。还有JWT的有效期和刷新机制,避免频繁重新登录。另外,后端接口的权限配置要全面,避免遗漏导致安全漏洞。前端路由的404处理,以及无权限访问时的提示页面也需要处理。 可能遇到的问题:动态路由的刷新白屏,需要保持Vuex中的状态持久化。后端权限变更后,前端如何实时更新,可能需要重新获取权限数据。还有接口权限和前端路由权限的同步问题,比如用户直接输入URL访问没有权限的页面,后端接口依然要拦截。 测试的时候,可以用不同角色的用户登录,检查是否有权限访问相应的接口和页面。按钮是否显示正确。同时,后端要确保每个接口都正确配置了权限注解,避免绕过前端直接调用接口的情况。 总的来说,步骤大概是:设计RBAC数据库结构,后端整合Spring Security实现权限验证,前端Vue动态路由和按钮控制,前后端通过JWT传递用户信息,保证接口权限校验的一致性和安全性。需要仔细处理每个环节的权限校验,避免漏洞。</think>以下分4个阶段实现基于RBAC的接口级权限控制(Spring Security + Vue方案): 一、数据库设计阶段(RBAC核心) ```sql /* 用户表 */ CREATE TABLE sys_user ( id BIGINT PRIMARY KEY, username VARCHAR(50) UNIQUE, password VARCHAR(100) ); /* 角色表 */ CREATE TABLE sys_role ( id BIGINT PRIMARY KEY, role_code VARCHAR(20) UNIQUE -- 如:ROLE_ADMIN ); /* 权限表 */ CREATE TABLE sys_permission ( id BIGINT PRIMARY KEY, perm_code VARCHAR(50) UNIQUE, -- 如:user:delete description VARCHAR(100) ); /* 用户角色关联表 */ CREATE TABLE user_role ( user_id BIGINT, role_id BIGINT ); /* 角色权限关联表 */ CREATE TABLE role_perm ( role_id BIGINT, perm_id BIGINT ); ``` 二、Spring Security后端实现 1. 自定义UserDetailsService ```java @Service public class UserDetailsServiceImpl implements UserDetailsService { @Autowired private UserMapper userMapper; @Override public UserDetails loadUserByUsername(String username) { // 查询用户基本信息 User user = userMapper.findByUsername(username); // 查询权限集合(格式:ROLE_xxx, user:add等) List<String> authorities = userMapper.findUserPermissions(user.getId()); return new AuthUser( user.getId(), user.getUsername(), user.getPassword(), AuthorityUtils.createAuthorityList(authorities) ); } } ``` 2. 配置方法级安全控制 ```java @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers("/login").permitAll() .anyRequest().authenticated() .and() .addFilterBefore(jwtAuthFilter(), UsernamePasswordAuthenticationFilter.class); } @Bean public JwtAuthFilter jwtAuthFilter() { return new JwtAuthFilter(); } } ``` 3. 接口权限注解使用 ```java @RestController @RequestMapping("/user") public class UserController { @PreAuthorize("hasAuthority('user:query')") @GetMapping("/{id}") public ResponseEntity<User> getUser(@PathVariable Long id) { // ... } @PreAuthorize("hasAuthority('user:delete')") @DeleteMapping("/{id}") public ResponseEntity<Void> deleteUser(@PathVariable Long id) { // ... } } ``` 三、Vue前端实现方案 1. 动态路由处理(router/index.js) ```javascript const createRouter = () => new Router({ routes: constantRoutes // 基础路由(登录页/404等) }) // 根据权限过滤动态路由 function filterAsyncRoutes(routes, permissions) { return routes.filter(route => { if (route.meta && route.meta.perms) { return permissions.some(perm => route.meta.perms.includes(perm)) } else { return true } }) } // 路由守卫 router.beforeEach(async (to, from, next) => { if (store.getters.token) { if (!store.getters.permissions.length) { // 获取用户权限信息 const { permissions } = await store.dispatch('user/getInfo') // 生成动态路由 const accessRoutes = await store.dispatch('permission/generateRoutes', permissions) router.addRoutes(accessRoutes) next({ ...to, replace: true }) } else { next() } } else { next('/login') } }) ``` 2. 按钮权限控制(自定义指令) ```javascript // directives/permission.js export default { inserted(el, binding, vnode) { const { value } = binding const permissions = store.getters.permissions if (value && value instanceof Array) { const hasPermission = permissions.some(perm => { return value.includes(perm) }) if (!hasPermission) { el.parentNode && el.parentNode.removeChild(el) } } else { throw new Error(`需要指定权限数组,如v-permission="['user:delete']"`) } } } ``` 四、前后端交互流程 1. 用户登录成功后获取: ```json { "token": "xxxx", "permissions": ["user:query", "order:manage", ...] } ``` 2. 接口请求规范: ```http GET /api/user/1 Authorization: Bearer xxxx ``` 3. 异常处理场景: - 403状态码:前端显示无权限提示 - 401状态码:跳转登录页 - 其他错误:统一错误处理 补充建议: 1. 权限编码规范: - 功能级:`模块:操作` 如 `user:add` - 数据级:`模块:操作:范围` 如 `order:view:department` 2. 开发注意事项: - 后端必须校验每个接口的权限,不能依赖前端控制 - 权限变更时需考虑JWT中权限信息的更新策略 - 定期审计接口权限配置,防止出现未受保护接口 3. 性能优化: - 后端缓存权限数据 - 前端使用localStorage缓存权限信息 - 动态路由按需加载组件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值