简单实现一个在springboot中动态权限的实时管理

以下这个案例将涉及到一个权限管理场景,假设我们有一个内部管理系统,管理员可以动态变更用户的权限。我们将演示在用户访问某个资源时,权限发生变更后,系统自动响应并及时反馈权限的变化。

场景描述

在这个场景中,用户有一个可以管理资源的页面,比如一个"订单管理系统",用户可以创建、编辑、删除订单。系统管理员可以动态更改用户的权限,比如撤销其"删除订单"的权限。当管理员更改用户权限后,前端页面会监听这个权限的变化。通过浏览器端订阅消息队列(MQ)的方式,实时地收到权限变化通知,并根据权限变动做出相应操作。

如果用户的权限被撤销,前端会立即更新显示。若用户尝试进行不允许的操作(例如删除操作),系统会弹出权限不足的提示。

技术要点:
  • Spring Boot作为后端框架。
  • RabbitMQ作为消息队列,实现权限变更的通知。
  • 前端使用WebSocket订阅RabbitMQ队列,监听权限变更。
  • 使用Spring Security进行权限控制。
  • 复杂场景:权限动态变更后,实时限制用户操作(删除按钮隐藏,弹出权限变更通知)。

解决方案

  1. Spring Boot后端处理权限变更: 当管理员修改了某个用户的权限,系统会将权限变更的消息发送到RabbitMQ队列,前端会通过WebSocket接收并实时更新页面。

  2. 前端处理权限变更: 用户页面通过WebSocket连接到后端,监听权限的变更。一旦收到权限变更消息,前端立即更新用户界面。

  3. MQ订阅与前端动态变动: WebSocket与RabbitMQ的结合使得权限变更可以及时反映在前端,无需手动刷新。若用户尝试操作失去权限的功能,会出现提示框告知用户权限不足。

实际代码实现

1. Spring Boot配置
配置RabbitMQ

在Spring Boot中配置RabbitMQ的连接和队列。

application.yml:

yaml 复制代码
spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
创建消息队列配置类
java 复制代码
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitConfig {

    public static final String PERMISSION_CHANGE_QUEUE = "permission_change_queue";

    @Bean
    public Queue permissionChangeQueue() {
        return new Queue(PERMISSION_CHANGE_QUEUE);
    }
}
权限变更服务
java 复制代码
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class PermissionChangeService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void notifyPermissionChange(String userId) {
        // 发送权限变更消息到队列
        rabbitTemplate.convertAndSend(RabbitConfig.PERMISSION_CHANGE_QUEUE, userId);
    }
}
模拟权限变更控制器
java 复制代码
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AdminController {

    @Autowired
    private PermissionChangeService permissionChangeService;

    @PreAuthorize("hasRole('ADMIN')")
    @PostMapping("/changePermission")
    public String changePermission(@RequestParam String userId, @RequestParam String newPermission) {
        // 修改数据库中的权限逻辑(省略)

        // 通知权限变更
        permissionChangeService.notifyPermissionChange(userId);

        return "Permissions updated for user: " + userId;
    }
}
WebSocket配置类
java 复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
    }
}
WebSocket消息发送服务
java 复制代码
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;

@Service
public class WebSocketNotificationService {

    private final SimpMessagingTemplate messagingTemplate;

    public WebSocketNotificationService(SimpMessagingTemplate messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
    }

    public void notifyUser(String userId, String message) {
        messagingTemplate.convertAndSend("/topic/permission/" + userId, message);
    }
}
消费者监听权限变更消息
java 复制代码
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class PermissionChangeListener {

    @Autowired
    private WebSocketNotificationService webSocketNotificationService;

    @RabbitListener(queues = RabbitConfig.PERMISSION_CHANGE_QUEUE)
    public void handlePermissionChange(String userId) {
        // 通知前端权限变更
        webSocketNotificationService.notifyUser(userId, "Your permissions have been changed. Please refresh.");
    }
}
2. 前端代码
WebSocket连接和权限监听

假设使用Vue.js前端框架。

WebSocket.js:

javascript 复制代码
import SockJS from 'sockjs-client';
import Stomp from 'stompjs';

let stompClient = null;

export function connect(userId, onPermissionChange) {
    const socket = new SockJS('/ws');
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function () {
        stompClient.subscribe('/topic/permission/' + userId, function (message) {
            onPermissionChange(JSON.parse(message.body));
        });
    });
}

export function disconnect() {
    if (stompClient !== null) {
        stompClient.disconnect();
    }
}
Vue组件中的使用
javascript 复制代码
<template>
  <div>
    <h1>Order Management</h1>
    <button v-if="canDelete" @click="deleteOrder">Delete Order</button>
    <p v-if="!canDelete" style="color:red">You do not have permission to delete orders</p>
  </div>
</template>

<script>
import { connect, disconnect } from '@/websocket';

export default {
  data() {
    return {
      canDelete: true
    };
  },
  created() {
    const userId = this.$store.state.user.id;
    connect(userId, this.handlePermissionChange);
  },
  beforeDestroy() {
    disconnect();
  },
  methods: {
    handlePermissionChange(message) {
      alert(message);
      this.canDelete = false; // 动态撤销删除权限
    },
    deleteOrder() {
      if (this.canDelete) {
        // 发送删除请求
      } else {
        alert('You do not have permission to delete this order.');
      }
    }
  }
};
</script>

运行流程

  1. 用户登录系统,进入"订单管理"页面。
  2. 管理员在后台更改用户权限,撤销其"删除订单"的权限。
  3. 后端通过RabbitMQ发送权限变更的消息,消息通过WebSocket通知前端用户。
  4. 前端页面接收到消息后,自动禁用"删除订单"按钮,用户再也无法点击该按钮。
  5. 若用户试图删除订单,系统会弹出权限不足的提示。

总结

这个案例展示了如何使用Spring Boot结合RabbitMQ和WebSocket处理权限动态变更的场景。通过实时监听权限变更并及时在前端做出反馈,可以确保用户操作权限的准确性,同时提高用户体验。

相关推荐
2401_8570262323 分钟前
医疗革新:Spring Boot医院管理系统
服务器·数据库·spring boot
那你为何对我三笑留情25 分钟前
三、Spring Boot集成Spring Security之securityFilterChain过滤器链详解
java·spring boot·spring·spring security·过滤器链
qq_2518364572 小时前
基于springboot vue在线学籍管理系统设计与实现
vue.js·spring boot·后端
CodeLinghu2 小时前
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
java·spring boot·后端
Slow菜鸟2 小时前
SpringBoot教程(二十四) | SpringBoot实现分布式定时任务之Quartz(动态新增、修改等操作)
spring boot·分布式·后端
夜色呦2 小时前
Spring Boot实现新闻个性化推荐
服务器·spring boot·php
疯一样的码农5 小时前
Spring Boot Starter Parent介绍
java·spring boot·后端
iQM755 小时前
Spring Boot集成RBloomFilter快速入门Demo
java·spring boot·spring
爱上语文5 小时前
Springboot 阿里云对象存储OSS 工具类
java·开发语言·spring boot·后端·阿里云
《源码好优多》6 小时前
基于微信小程序的生鲜订购小程序系统(SpringBoot+Vue+Uniapp+MySQL)
spring boot·微信小程序·小程序