JAX-RS使用的无状态EJB中的@Context注入

我在下面有这样的设置。 这是一个简化版本,但我认为它得到了基本的想法。 我使用的是Jersey 2.16,Java 1.8和Glassfish Open Source 4.1

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服务时,我从安全上下文中获取了NullPointerexception。 似乎根本没有注入Context。 我检查过它是secContext变量本身,而不仅仅是getUserPrincipal()的返回值为null。 除了我的NullPointer之外,Glassfish日志中没有警告或exception(导致向Web客户端返回500错误)。

问题是您在错误的地方使用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文档 – 第16章。安全性 。

在EJB内部,您必须使用EJBContext (或SessionContext )。

谢谢,我已经解决了使用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看到与JAX-RS servlet相同的Principal。