切換語言為:簡體

SpringBoot實現一個實時許可權變更系統,及時在前端做出反饋!

  • 爱糖宝
  • 2024-10-10
  • 2037
  • 0
  • 0

以下這個案例將涉及到一個許可權管理場景,假設我們有一個內部管理系統,管理員可以動態變更使用者的許可權。我們將演示在使用者訪問某個資源時,許可權發生變更後,系統自動響應並及時反饋許可權的變化。

場景描述

在這個場景中,使用者有一個可以管理資源的頁面,比如一個“訂單管理系統”,使用者可以建立、編輯、刪除訂單。系統管理員可以動態更改使用者的許可權,比如撤銷其“刪除訂單”的許可權。當管理員更改使用者許可權後,前端頁面會監聽這個許可權的變化。透過瀏覽器端訂閱訊息佇列(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:

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>

執行流程

  1. 使用者登入系統,進入“訂單管理”頁面。

  2. 管理員在後臺更改使用者許可權,撤銷其“刪除訂單”的許可權。

  3. 後端透過RabbitMQ傳送許可權變更的訊息,訊息透過WebSocket通知前端使用者。

  4. 前端頁面接收到訊息後,自動禁用“刪除訂單”按鈕,使用者再也無法點選該按鈕。

  5. 若使用者試圖刪除訂單,系統會彈出許可權不足的提示。

總結

這個案例展示瞭如何使用Spring Boot結合RabbitMQ和WebSocket處理許可權動態變更的場景。透過實時監聽許可權變更並及時在前端做出反饋,可以確保使用者操作許可權的準確性,同時提高使用者體驗。

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.