首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring AOP 實戰:方法攔截驗證使用者權限

     編輯:Java 相關知識

前言

Spring AOP(面向切面程式設計)能將權限檢查、日誌、交易等橫切關注點與業務邏輯解耦。本範例示範如何使用 MethodBeforeAdvice 在方法執行前驗證使用者身分,僅允許特定帳號存取受保護方法。

專案結構

aop.secure
├── UserInfo.java          // 使用者資料模型
├── SecureBean.java        // 受保護的業務元件
├── SecurityAdvice.java    // 切面:方法前置通知
├── SecurityManager.java   // 登入/登出狀態管理
└── SecurityExample.java   // 測試入口

核心程式碼

1. UserInfo.java - 使用者資料

package aop.secure;

public class UserInfo {
    private String userName;
    private String password;

    public UserInfo(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }
    public String getUserName() { return userName; }
    public String getPassword() { return password; }
}

2. SecureBean.java - 受保護業務

package aop.secure;

public class SecureBean {
    public void writeSecureMessage() {
        System.out.println("Every time I learn something new and it pushes some old stuff out of my brain.");
    }
}

3. SecurityAdvice.java - 切面實作 MethodBeforeAdvice

package aop.secure;

import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;

public class SecurityAdvice implements MethodBeforeAdvice {
    private SecurityManager securityManager = new SecurityManager();

    public void before(Method method, Object[] args, Object target) throws Throwable {
        UserInfo user = securityManager.getLoggedOnUser();
        if (user == null) {
            System.out.println("No user authenticated.");
            throw new SecurityException("Method name: " + method.getName());
        } else if ("chigo".equals(user.getUserName()) && "chigo".equals(user.getPassword())) {
            System.out.println("OKAY! Access granted.");
        } else {
            System.out.println("Logged in user is: " + user.getUserName());
            throw new SecurityException("User " + user.getUserName() + " is not allowed access to method " + method.getName());
        }
    }
}

4. SecurityManager.java - 執行緒區域儲存登入狀態

package aop.secure;

public class SecurityManager {
    private static ThreadLocal<UserInfo> local = new ThreadLocal<UserInfo>();

    public void login(String userName, String password) {
        local.set(new UserInfo(userName, password));
    }
    public void logout() { local.set(null); }
    public UserInfo getLoggedOnUser() { return local.get(); }
}

5. SecurityExample.java - 整合測試

package aop.secure;

import org.springframework.aop.framework.ProxyFactory;

public class SecurityExample {
    private static SecureBean getSecureBean() {
        SecureBean target = new SecureBean();
        SecurityAdvice advice = new SecurityAdvice();
        ProxyFactory pf = new ProxyFactory();
        pf.setTarget(target);
        pf.addAdvice(advice);
        return (SecureBean) pf.getProxy();
    }

    public static void main(String[] args) {
        SecurityManager mgr = new SecurityManager();
        SecureBean bean = getSecureBean();

        // 合法使用者
        mgr.login("chigo", "chigo");
        bean.writeSecureMessage();  // 成功
        mgr.logout();

        // 非法使用者
        try {
            mgr.login("kkk", "");
            bean.writeSecureMessage();
        } catch (SecurityException ex) {
            System.out.println("Exception caught: " + ex.getMessage());
        } finally {
            mgr.logout();
        }

        // 未登入
        try {
            bean.writeSecureMessage();
        } catch (SecurityException ex) {
            System.out.println("Exception caught: " + ex.getMessage());
        }
    }
}

執行結果

OKAY! Access granted.
Every time I learn something new and it pushes some old stuff out of my brain.
Logged in user is: kkk
Exception caught: User kkk is not allowed access to method writeSecureMessage
No user authenticated.
Exception caught: Method name: writeSecureMessage

關鍵點解析

  • ProxyFactory:Spring AOP 核心,為目標物件建立代理,攔截方法呼叫。
  • MethodBeforeAdvice:在目標方法執行前執行通知邏輯,適合權限預檢。
  • ThreadLocal:確保每條執行緒獨立擁有登入狀態,避免多執行緒環境下資料競爭。
  • SecurityException:拋出未受檢異常中斷方法執行,模擬存取被拒絕。

擴充建議

  1. 將合法帳號移至設定檔或資料庫,支援角色基礎存取控制(RBAC)。
  2. 改用 @AspectJ 註解風格(Spring 2.0+),減少 XML 配置。
  3. 結合 AfterReturningAdvice 或 ThrowsAdvice 實現存取稽核日誌。
  4. 整合 Spring Security 取代手工實作,獲得完整認證授權框架。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved