2012-11-29 108 views
2

我一直在嘗試使用註釋而不是部署描述符將應用程序部署到glassfish 3。但是,我一直無法正常工作。如果我嘗試訪問該服務,我結束了一個服務器錯誤500,顯示此消息:使用註釋基本身份驗證來保護Glassfish REST服務

type Exception report 

message 

descriptionThe server encountered an internal error() that prevented it from fulfilling this request. 

exception 

javax.servlet.ServletException: javax.ejb.AccessLocalException: Client not authorized for this invocation 
root cause 

javax.ejb.AccessLocalException: Client not authorized for this invocation 

的EJB看起來是這樣的:

@Path("/myresource") 
@Stateless 
@RolesAllowed("user-role") 
public class MyResource { 

    @GET 
    @Path("/{uuid}") 
    public Response getData(@PathParam("uuid") final String uuid) { 
      .... 
    } 
} 

sun-web.xml中:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD GlassFish Application Server 3.0 Servlet 3.0//EN" 
"http://www.sun.com/software/appserver/dtds/sun-web-app_3_0-0.dtd"> 
<sun-web-app> 
    <security-role-mapping> 
     <role-name>user-role</role-name> 
     <group-name>user-group</group-name> 
    </security-role-mapping> 
</sun-web-app> 

這是在web.xml:

<web-app id="myservice" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 

    <display-name>org.test.myservice</display-name> 

    <servlet> 
     <servlet-name>Jersey Web Application</servlet-name> 
     <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> 
     <init-param> 
      <param-name>com.sun.jersey.config.property.packages</param-name> 
      <param-value>org.test.myservice.rest</param-value> 
     </init-param> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 

    <servlet-mapping> 
     <servlet-name>Jersey Web Application</servlet-name> 
     <url-pattern>/*</url-pattern> 
    </servlet-mapping> 

    <login-config> 
     <auth-method>BASIC</auth-method> 
     <realm-name>file</realm-name> 
    </login-config> 

    <security-role> 
     <role-name>user-role</role-name> 
    </security-role> 
</web-app> 

glassfish中的文件領域使用sun-web.xml中指定的用戶和角色進行設置,並且在通過部署描述符設置應用程序安全性時一直運行良好。

如果我正確理解這個文檔,我不必鏈接安全角色引用,如果他們的名字是相同的。 http://docs.oracle.com/javaee/5/tutorial/doc/bnbyl.html#bnbyt 任何想法我失蹤?

編輯 相關的不能夠指定與註釋所需的信息的問題,是有另外一個問題,這引起了我的思考這個問題。也許這會使最初的問題更清楚一些: 上面舉例說明,resource/myresource/*僅適用於角色爲'user-role'的用戶。但是,如果在path/myresource/*/thumbnail上存在第二個資源(轉換爲/ myresource/[uuid]/thumbnail),則應該在沒有身份驗證的情況下使用這個資源,因爲使用url-mapping指定安全約束是不可能的,因爲它似乎不可能在常量之間使用通配符。但是,通過指定允許通過註釋訪問方法的角色,這將是可行的。如上所述,我還沒有做到。這樣的映射怎麼可能完成?

+0

您如何訪問寧靜的Web服務MyResource?直接從客戶端?或者在服務器端內部? (如何)你是否認證了客戶? – perissf

+0

我使用瀏覽器訪問它,因爲它只是一個獲取請求。但是,我們也有測試,它們使用apache http客戶端來訪問資源。客戶端應通過基本身份驗證進行身份驗證。所以,瀏覽器應該自動顯示一個彈出窗口。 apache http客戶端被配置爲發送憑據。我只是做了更多的測試。只要我從舊的web.xml中刪除安全約束部分,我就會發現http 500錯誤。這對我來說沒有任何意義... –

+0

您是否在web.xml中添加了安全約束元素? – perissf

回答

2

您需要在web.xml描述符中使用security-constraint元素,以便阻止特定資源和路徑以及指定授權約束。

這並不意味着你不能添加使用程序安全性更細粒度的控制,如Oracle's Java EE 6 Tutorial解釋說:

程序安全性嵌入到應用程序,用於進行安全決策。僅當聲明式安全性不足以表達應用程序的安全模型時,程序式安全性非常有用。


根據你編輯問題。

我會使用security-constraint元素來阻止對所有未註冊用戶的訪問。這將強制每個人進行身份驗證,以便您的應用程序知道他們的角色。 然後,您可以使用程序化安全性細粒度地控制對各種資源的訪問。

使用基本認證我猜沒有其他方法。如果您希望避免基本用戶的身份驗證,則需要使用表單身份驗證並在後臺以編程方式處理身份驗證,並使用HttpServletRequest#login()對身份進行身份驗證(即使他們不知道)。

在這兩種方式中,您應該能夠以您所描述的方式設置權限。如果你想更順暢處理未授權的例外,你最好刪除@RolesAllowed註釋,而是使用類似:

@GET 
@Path("/{uuid}") 
public Response getData(@PathParam("uuid") final String uuid, @Context SecurityContext sc) { 
    if (sc.isUserInRole("MyRole")) { 
     return result; 
    } else { 
     return notAllowedResult; 
    } 
} 
+0

不幸的是,我還是不完全明白。如果我想補充像<安全約束>安全約束 \t \t <網絡資源收集> \t \t \t <網絡資源名稱>安全 \t \t \t /myresource/* \t \t \t GET \t \t \t \t \t \t \t 用戶角色 \t \t \t註釋的目的是什麼?方法上的註釋本質上提供了與安全約束(例如路徑(url),角色和方法)相同的信息。 –

+0

No. @Path註釋是Jersey-REST資源路徑。它與安全無關。 – perissf

+0

好吧,如果我現在正確地理解了這一點,基本驗證由澤西servlet提供,它由安全約束配置。由於球衣網址映射不支持取決於通配符之後的值的映射,因此我無法禁用* /縮略圖資源的基本身份驗證。所以,最後我不能使用基本身份驗證來配置球衣來做我想做的事情。如果我只想依賴註釋,我不會得到人們通常期望的基本身份驗證處理,但是在EJB級別上是安全的。它是否正確? –

2

的角色允許的是EJB結構而非全等對資源的訪問,這由安全約束處理。

不幸的是,這兩個安全概念並沒有像他們應該那樣進行網格劃分,而是如果您沒有獲得授權(網絡概念)而不是獲得401,您會得到您正在接收的安全異常(以及EJB概念)。事實上,如果您使用RolesAllowed註釋EJB Web服務並嘗試訪問具有無效角色的Web服務,我不知道您會收到什麼錯誤。在這種情況下,我認爲你會得到一個SOAP錯誤。

EJB安全性是一個讓未經授權的人離開的系統,但這是最後一次努力。它假定任何將人員路由到方法調用的決定都已經完成。例如,沒有高級別的方法來測試一個方法是否被允許,而只能調用它並捕獲異常。

因此,嚴酷的事實超越了粗俗的守門人,您想要利用程序化安全。

+0

謝謝。我想我已經理解了,爲什麼我不能使用@RolesAllowed註釋來保護我的資源。不過,我仍然在尋找一種方法來獲得基本的身份驗證安全資源/ myresource/*和後續的開放資源/ myresource/* /縮略圖。有沒有什麼辦法可以實現這一點,而不是跳過籃球? –

+0

您是否設法解決該問題?我有同樣的:http://stackoverflow.com/questions/15947415/basic-authentication-in-rest-application – Sami

相關問題