2015-03-18 56 views
1

我在下面有類似下面的設置。這是一個簡化的版本,但我認爲它得到了基本的想法。我用的澤西2.16,爪哇1.8和Glassfish開源4.1JAX-RS使用的無狀態EJB中的@Context注入

public interface IReportService { 
    String addNewReport(Report report); 
} 

@Path("reports") 
public class ReportResource implements IReportService { 
    /** 
    * Service layer. 
    */ 
    @EJB 
    private transient ReportService service; 

    @POST 
    @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) 
    @Produces(MediaType.TEXT_PLAIN) 
    @Override 
    public String addNewReport(final Report report) { 
     return service.addNewReport(report); 
    } 
} 

@Stateless 
@LocalBean 
public class ReportService implements IReportService { 

    @EJB 
    private IReportPersistence reportPersistence; 

    @Context 
    SecurityContext secContext; 

    public String addNewReport(final Report report) { 
     report.setUserName(secContext.getUserPrincipal().getName()); 
     reportPersistence.persist(report); 
    } 
} 

但是當我部署和嘗試打web服務我從安全上下文一個空指針異常。看起來Context並沒有被注入。我檢查過,它是secContext變量本身,而不是getUserPrincipal()返回的null。除了我的NullPointer之外,Glassfish日誌中沒有任何警告或例外(這會導致500錯誤返回給Web客戶端)。

回答

3

問題是您在錯誤的地方使用了SecurityContext。你必須在你的REST資源類中使用它。

你可以嘗試以下方法:

@POST 
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) 
@Produces(MediaType.TEXT_PLAIN) 
@Override 
public String addNewReport(final Report report, @Context SecurityContext sc) { 
    report.setUserName(sC.getUserPrincipal().getName()); 
    return service.addNewReport(report); 
} 

對於更多的細節來看看Jersey Documentation - Chapter 16. Security

在EJB內部,您必須使用EJBContext(或SessionContext)。

+0

啊我明白了。我希望Request Scoped SecurityContext能夠映射到無狀態EJB中。雖然看起來沒有運氣。有點討厭Glassfish不會拋出警告或錯誤,說明無法處理註釋和注入值。我需要做的任何事情才能讓EJBContext注入?我已經嘗試過了,它也是空的。 – astropcr 2015-03-19 14:39:15

2

謝謝,我已經解決了在EJB中使用EJBContext,正如unwichtich所指出的那樣。

總而言之,SecurityContext僅適用於JAX-RS bean,我已將EJBContext對象放置到SecurityContext的其他java bean中。 您也可以使用SessionContext對象,但EJBContext接口類似於SecurityContext對象。下面是一個使用示例:

@DeclareRoles({"administrator","operator","user"}) 
@PermitAll 
@Stateless 
public class myFacade { 

    @PersistenceContext(unitName = "myPersistencePU") 
    private EntityManager em; 

    @Resource EJBContext securityContext; 

    public DataStuff find(Object id) { 
     //Now the securityContext is != null :-D 
     String username = securityContext.getCallerPrincipal().getName(); 
     if(username.equals("gino"){ 
      return null; 
     } 
     return getEntityManager().find(entityClass, id); 
    } 
} 

它將按預期自動神奇的EJB看到相同的校長(S)爲JAX-RS的servlet做。