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

Java EE 5 安全註解實戰:基於 JSR 250 的身份驗證與授權機制

     編輯:Java 相關知識

前言:從部署描述符到註解驅動的安全模型

Java EE 5 引入 JSR 250 通用註解,將安全配置從 ejb-jar.xml/web.xml 遷移至 Java 代碼,簡化開發、縮短週期。本文系統梳理 5 大安全註解在 EJB、Servlet、Web Service 中的適用規則、繼承語義與部署描述符覆蓋機制。

五大核心安全註解(JSR 250)

註解目標EJBServletWeb Service核心用途
@PermitAll類/方法✓✗✓允許所有用戶訪問(含未認證)
@DenyAll方法✓✗✓禁止所有用戶訪問
@RolesAllowed類/方法✓✗✓指定允許訪問的角色列表
@DeclareRoles類✓✓✓聲明組件使用的角色,供 isCallerInRole 檢查
@RunAs類✓✓✗指定組件以何種角色身份執行

關鍵限制: @PermitAll/@DenyAll/@RolesAllowed **不支援 Servlet**,Web 模組仍需在 web.xml 定義 <security-constraint>。

註解使用範例與優先級

@Stateless
@RolesAllowed("javaee")  // 類級:預設所有方法需 javaee 角色
public class HelloEJB implements Hello {

    @PermitAll             // 方法級覆蓋:hello() 允許匿名訪問
    public String hello(String msg) { return "Hello, " + msg; }

    public String bye(String msg) { return "Bye, " + msg; } // 繼承類級,需 javaee 角色
}

規則: 方法級註解覆蓋類級;同一方法不可同時標註 @PermitAll/@DenyAll/@RolesAllowed;@RolesAllowed 僅能出現一次,多角色用陣列 @RolesAllowed({"admin","user"})。

@DeclareRoles:複雜授權邏輯的基石

當授權決策需動態判斷(如「屬於角色 A 且不屬於角色 B」)時,單純註解不夠,需結合 @DeclareRoles 聲明角色,並在代碼中調用上下文 API:

組件檢查角色 API
EJBSessionContext.isCallerInRole(role)
ServletHttpServletRequest.isUserInRole(role)
Web ServiceWebServiceContext.isUserInRole(role)
@Stateless
@DeclareRoles({"A", "B"})
public class HelloEJB implements Hello {
    @Resource SessionContext ctx;

    public String hello(String msg) {
        if (ctx.isCallerInRole("A") && !ctx.isCallerInRole("B")) {
            return "Allowed: " + msg;
        }
        return "Denied";
    }
}

註解繼承語義

註解繼承規則
@PermitAll/@DenyAll/@RolesAllowed方法級:採用繼承鏈中被調用方法的註解;類級:被子類繼承,方法級覆蓋類級
@RunAs**僅考慮葉節點(具體實現類)的註解**,父類忽略
@DeclareRoles**疊加合併**:繼承鏈中所有聲明的角色彙總

部署描述符覆蓋註解(XML 勝出)

若同時存在註解與 ejb-jar.xml/web.xml,**部署描述符優先**。示例:

// EJB 註解
@Stateless
public class HelloEJB {
    @PermitAll public String hello1() { return "1"; }
    @RolesAllowed("javaee") public String hello2() { return "2"; }
    @DenyAll public String hello3() { return "3"; }
}

ejb-jar.xml 覆蓋:

<assembly-descriptor>
  <security-role><role-name>javaee</role-name></security-role>
  <method-permission>
    <role-name>javaee</role-name>
    <method><ejb-name>HelloEJB</ejb-name><method-name>hello1</method-name></method>
  </method-permission>
  <method-permission>
    <unchecked/>  <!-- 等同 @PermitAll -->
    <method><ejb-name>HelloEJB</ejb-name><method-name>hello3</method-name></method>
  </method-permission>
  <exclude-list>  <!-- 等同 @DenyAll -->
    <method><ejb-name>HelloEJB</ejb-name><method-name>hello2</method-name></method>
  </exclude-list>
</assembly-descriptor>

結果: hello1 需 javaee 角色;hello2 禁止訪問;hello3 允許所有。

Web 模組安全配置(web.xml 必寫)

<security-constraint>
  <web-resource-collection>
    <web-resource-name>SecureArea</web-resource-name>
    <url-pattern>/admin/*</url-pattern>
    <http-method>GET</http-method>
    <http-method>POST</http-method>
  </web-resource-collection>
  <auth-constraint>
    <role-name>employee</role-name>
  </auth-constraint>
</security-constraint>

<login-config>
  <auth-method>BASIC</auth-method>  <!-- 或 FORM -->
  <realm-name>default</realm-name>
</login-config>

<security-role><role-name>employee</role-name></security-role>

角色映射:應用角色 → 伺服器群組/主體

在 sun-application.xml / sun-ejb-jar.xml / sun-web.xml 中映射:

<security-role-mapping>
  <role-name>employee</role-name>
  <group-name>engineer</group-name>  <!-- 映射到伺服器 engineer 群組 -->
</security-role-mapping>

@RunAs 執行身份與主體綁定

EJB 在 sun-ejb-jar.xml 指定主體:

<ejb>
  <ejb-name>HelloEJB</ejb-name>
  <principal><name>user1</name></principal>
</ejb>

Servlet 在 sun-web.xml 指定:

<servlet>
  <servlet-name>myServlet</servlet-name>
  <principal-name>user1</principal-name>
</servlet>

實施步驟總結

  1. 建立 Java EE 應用,EJB 掛安全註解,Web 模組寫 web.xml 安全約束。
  2. 在部署描述符添加 <login-config> 指定認證方式(BASIC/FORM)與 Realm。
  3. 如非預設 Realm,建立自定義 Realm(檔案/LDAP/JDBC/PAM)。
  4. 在運行時描述符(sun-*.xml)添加 <security-role-mapping> 完成角色映射。
  5. 指定 @RunAs 組件的主體身份。
  6. 打包部署驗證。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved