1

如果我不添加以下注释行,我有以下 jax-rs Restful API 可以正常工作

@RolesAllowed("AdminRole")

以上 GET 注解

package service;

import entities.Booking;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.annotation.security.DeclareRoles;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;


@PermitAll
@Stateless
@Path("entities.booking")
public class BookingFacadeREST extends AbstractFacade<Booking> {
    @PersistenceContext(unitName = "ofserverDBPU")

    private EntityManager em;

    public BookingFacadeREST() {
        super(Booking.class);
    }

    @POST
    @Override
    @Consumes({"application/xml", "application/json"})
    public void create(Booking entity) {
        super.create(entity);
    }

    @PUT
    @Override
    @Consumes({"application/xml", "application/json"})
    public void edit(Booking entity) {
        super.edit(entity);
    }

    @DELETE
    @Path("{id}")
    public void remove(@PathParam("id") Integer id) {
        super.remove(super.find(id));
    }

    @GET
    @Path("{id}")
    @Produces({"application/xml", "application/json"})
    public Booking find(@PathParam("id") Integer id) {
        return super.find(id);
    }

    @RolesAllowed("AdminRole")
    @GET
    @Override
    @Produces({"application/xml", "application/json"})        
    public List<Booking> findAll() {
        return super.findAll();
    }

    @GET
    @Path("{from}/{to}")
    @Produces({"application/xml", "application/json"})
    public List<Booking> findRange(@PathParam("from") Integer from, @PathParam("to") Integer to) {
        return super.findRange(new int[]{from, to});
    }

    @GET
    @Path("count")
    @Produces("text/plain")
    public String countREST() {
        return String.valueOf(super.count());
    }

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

}

通过放置上面的注释给出以下错误。

HTTP Status 500 - Internal Server Error

type Exception report

messageInternal Server Error

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

exception

javax.servlet.ServletException: javax.ejb.EJBAccessException
root cause

javax.ejb.EJBAccessException
root cause

javax.ejb.AccessLocalException: Client not authorized for this invocation
note The full stack traces of the exception and its root causes are available in the GlassFish Server Open Source Edition 4.0 logs.

GlassFish Server Open Source Edition 4.0

我在哪里做错了?

4

1 回答 1

0

它有点老了,但我仍然有同样的问题(注意我也有一个自定义的SecurityContext. 徘徊了一段时间后,我终于通过编写自己的“@RolesAllowed注释”来实现它。

这是我如何进行的:

首先,新建一个注解:

@NameBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Secured {
    String role() default "all";
}

然后,在身份验证阶段使用ContainerRequestFilter运行并检查权限:

@Provider
@Priority(Priorities.AUTHENTICATION)
public class SecurityFilter implements ContainerRequestFilter {

    @Context
    private ResourceInfo resourceInfo;

     @Override
     public void filter(ContainerRequestContext crc) throws IOException {
         // get annotation (only for secured method)
        Secured security = resourceInfo.getResourceMethod().getAnnotation(Secured.class);
        if(security == null){
            // no security on method: check the class 
            security = resourceInfo.getResourceClass().getAnnotation(Secured.class);
            if(security == null) return;
        }

        // check the security, for example through the header:
        //   crc.getHeaderString("token") 
        // You can also inject a PersistenceContext and query your db

        // if the security check fails, use crc.abort() method
        // else, set the security context
        crc.setSecurityContext(new AppSecurityContext(userId, security.role()));
     }
 }

此过滤器必须通过web.xml或使用构造函数中的register方法注册Application

对于AppSecurityContext,看看这个教程。稍后可以通过以下方式在您的服务中访问它:

@Context
SecurityContext sctx;

最后,使用 . 注释您的类或方法(或两者)@Secure(role = "somerole")

于 2016-07-12T05:37:53.337 回答