springboot中动态权限实时管理的实现详解
作者:一只爱撸猫的程序猿
以下这个案例将涉及到一个权限管理场景,假设我们有一个内部管理系统,管理员可以动态变更用户的权限。我们将演示在用户访问某个资源时,权限发生变更后,系统自动响应并及时反馈权限的变化。
场景描述
在这个场景中,用户有一个可以管理资源的页面,比如一个“订单管理系统”,用户可以创建、编辑、删除订单。系统管理员可以动态更改用户的权限,比如撤销其“删除订单”的权限。当管理员更改用户权限后,前端页面会监听这个权限的变化。通过浏览器端订阅消息队列(MQ)的方式,实时地收到权限变化通知,并根据权限变动做出相应操作。
如果用户的权限被撤销,前端会立即更新显示。若用户尝试进行不允许的操作(例如删除操作),系统会弹出权限不足的提示。
技术要点
Spring Boot作为后端框架。
RabbitMQ作为消息队列,实现权限变更的通知。
前端使用WebSocket订阅RabbitMQ队列,监听权限变更。
使用Spring Security进行权限控制。
复杂场景:权限动态变更后,实时限制用户操作(删除按钮隐藏,弹出权限变更通知)。
解决方案
Spring Boot后端处理权限变更: 当管理员修改了某个用户的权限,系统会将权限变更的消息发送到RabbitMQ队列,前端会通过WebSocket接收并实时更新页面。
前端处理权限变更: 用户页面通过WebSocket连接到后端,监听权限的变更。一旦收到权限变更消息,前端立即更新用户界面。
MQ订阅与前端动态变动: WebSocket与RabbitMQ的结合使得权限变更可以及时反映在前端,无需手动刷新。若用户尝试操作失去权限的功能,会出现提示框告知用户权限不足。
实际代码实现
1. Spring Boot配置
配置RabbitMQ
在Spring Boot中配置RabbitMQ的连接和队列。
application.yml:
spring: rabbitmq: host: localhost port: 5672 username: guest password: guest
创建消息队列配置类
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); } }
权限变更服务
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); } }
模拟权限变更控制器
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配置类
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消息发送服务
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); } }
消费者监听权限变更消息
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:
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组件中的使用
<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>
运行流程
用户登录系统,进入“订单管理”页面。
管理员在后台更改用户权限,撤销其“删除订单”的权限。
后端通过RabbitMQ发送权限变更的消息,消息通过WebSocket通知前端用户。
前端页面接收到消息后,自动禁用“删除订单”按钮,用户再也无法点击该按钮。
若用户试图删除订单,系统会弹出权限不足的提示。
总结
这个案例展示了如何使用Spring Boot结合RabbitMQ和WebSocket处理权限动态变更的场景。通过实时监听权限变更并及时在前端做出反馈,可以确保用户操作权限的准确性,同时提高用户体验。
到此这篇关于springboot中动态权限实时管理的实现详解的文章就介绍到这了,更多相关springboot动态权限实时管理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!