springboot中动态权限实时管理的实现详解

 更新时间:2024年10月31日 09:28:33   作者:一只爱撸猫的程序猿  
这篇文章主要为大家详细介绍了如何简单实现一个在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动态权限实时管理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用Java应用程序添加或删除 PDF 中的附件

    使用Java应用程序添加或删除 PDF 中的附件

    当我们在制作PDF文件或者PPT演示文稿的时候,为了让自己的文件更全面详细,就会在文件中添加附件,那么如何添加或删除PDF中的附件呢,今天通过本文给大家详细讲解,需要的朋友参考下吧
    2023-01-01
  • Java并发编程之重入锁与读写锁

    Java并发编程之重入锁与读写锁

    这篇文章主要介绍了Java并发编程之重入锁与读写锁,文中相关实例代码详细,测试可用,具有一定参考价值,需要的朋友可以了解下。
    2017-09-09
  • Java中List遍历删除元素remove()的方法

    Java中List遍历删除元素remove()的方法

    这篇文章主要介绍了Java中List遍历删除元素remove()的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • 使用IDEA创建Java Web项目并部署访问的图文教程

    使用IDEA创建Java Web项目并部署访问的图文教程

    本文通过图文并茂的形式给大家介绍了使用IDEA创建Java Web项目并部署访问的教程,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-08-08
  • Java的垃圾强制回收实例分析

    Java的垃圾强制回收实例分析

    这篇文章主要介绍了Java的垃圾强制回收,结合实例形式分析了java垃圾强制回收的相关原理及实现方法,需要的朋友可以参考下
    2019-08-08
  • Javaweb resin4如何配置端口虚拟目录

    Javaweb resin4如何配置端口虚拟目录

    这篇文章主要介绍了Javaweb resin4如何配置端口虚拟目录,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • Mybatis一对多与多对一查询处理详解

    Mybatis一对多与多对一查询处理详解

    这篇文章主要给大家介绍了关于Mybatis一对多与多对一查询处理的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • 通过实例了解JavaBean开发及使用过程解析

    通过实例了解JavaBean开发及使用过程解析

    这篇文章主要介绍了通过实例了解JavaBean开发及使用过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • Spring实战之使用c:命名空间简化配置操作示例

    Spring实战之使用c:命名空间简化配置操作示例

    这篇文章主要介绍了Spring实战之使用c:命名空间简化配置操作,结合实例形式详细分析了Spring使用c:命名空间简化配置的相关接口与配置操作技巧,需要的朋友可以参考下
    2019-12-12
  • JAVA多线程之中断机制及处理中断的方法

    JAVA多线程之中断机制及处理中断的方法

    这篇文章主要记录使用 interrupt() 方法中断线程,以及如何对InterruptedException进行处理,感觉对InterruptedException异常进行处理是一件谨慎且有技巧的活儿,需要的朋友可以参考下
    2023-02-02

最新评论