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

Spring遠程調用用戶身份傳播問題分析與解決

     編輯:Java 相關知識

問題現場

多平台架構:P1/P2/P3分別部署於不同服務器。用戶user1調用P1上的EJB,P1需以user2(配置文件指定)調用P2上的EJB。但控制台顯示P1仍使用user1身份調用P2。

配置文件分析

<bean id="XXX" class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean" lazy-init="true">
  <property name="jndiName"><value>XXX</value></property>
  <property name="jndiTemplate"><ref local="XXXJndiTemplate"/></property>
  <property name="businessInterface"><value>XXXXXX</value></property>
</bean>

<bean id="XXXJndiTemplate" class="org.springframework.jndi.JndiTemplate">
  <property name="environment">
    <props>
      <prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
      <prop key="java.naming.provider.url">${XX.url}</prop>
      <prop key="java.naming.security.principal">${XX.username}</prop>  <!-- user2 -->
      <prop key="java.naming.security.credentials">${XX.password}</prop>
    </props>
  </property>
</bean>

根因分析

WebLogic安全上下文傳播機制

WebLogic默認啟用安全上下文傳播:當客戶端(此處P1作為客戶端)已有認證上下文時,JNDI查找與EJB調用將忽略JndiTemplate中配置的principal/credentials,改用當前線程的安全上下文(user1)。

驗證方法

在P1調用P2前檢查線程上下文:

Subject subject = Subject.getSubject(AccessController.getContext());
// 或 WebLogic專用
weblogic.security.Security.getCurrentSubject();

若非null,說明存在傳播上下文。

解決方案

方案一:關閉安全上下文傳播(推薦)

在P1的weblogic.xml或啟動參數設置:

-Dweblogic.security.disableContextPropagation=true

或代碼級控制:

import weblogic.security.Security;
Security.runAs(subject, new PrivilegedAction() {
    public Object run() {
        // 此處調用P2 EJB,使用JndiTemplate配置的user2
        return p2Service.doBusiness();
    }
});

方案二:顯式指定調用身份

使用Spring的SimpleRemoteStatelessSessionProxyFactoryBean子類化,覆蓋create()方法:

public class CustomRemoteProxy extends SimpleRemoteStatelessSessionProxyFactoryBean {
    protected Object create() throws NamingException {
        // 構建帶user2憑證的Context
        Hashtable env = new Hashtable();
        env.put(Context.SECURITY_PRINCIPAL, "user2");
        env.put(Context.SECURITY_CREDENTIALS, "pwd2");
        Context ctx = new InitialContext(env);
        return ctx.lookup(getJndiName());
    }
}

方案三:WebLogic專用身份斷言

配置P1為可信任域,P2接受P1的身份斷言:

  • P1域設置Credential Mapper映射user1→user2
  • P2域配置Identity Asserter信任P1域令牌
  • 需WebLogic安全領域專家配置,屬基礎設施層解決

最佳實踐建議

  1. 明確邊界:服務間調用應顯式聲明身份,不依賴隱式傳播
  2. 統一配置:將遠程調用身份集中管理在配置中心
  3. 測試驗證:集成測試中包含跨服務身份驗證用例
  4. 文檔記錄:架構文檔明確標註服務間調用身份策略

總結

Spring配置正確但被WebLogic安全上下文傳播特性覆蓋。通過JVM參數關閉傳播或代碼級runAs隔離可強制使用配置身份user2。建議架構層面明確服務間身份傳播策略,避免隱式行為導致安全審計風險。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved