Служба jax-rs RolesAllowed Annotation бросает исключение

У меня есть следующий jax-rs Restful API, который отлично работает, если я не добавлю следующую строку аннотации

@RolesAllowed("Роль администратора")

над аннотацией 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

Где я делаю неправильно?


person Developer    schedule 08.11.2013    source источник
comment
Я использую localhost localhost:8080/ofserverDB/webresources/entities.booking без аннотации RoleAllow он возвращает xml-файл из базы данных. что правильно. но с аннотацией предполагается запросить базовую аутентификацию для проверки имени пользователя и пароля, а не вернуть исключение.   -  person Developer    schedule 08.11.2013
comment
Я выполнил настройку в web.xml и glassfish-web.xml и протестировал их в базовом веб-приложении, и они отлично работали для базовой аутентификации http. Так что я не думаю, что в этих файлах что-то не так. Я должен что-то упустить (например, аннотацию) в файле служб Java   -  person Developer    schedule 08.11.2013
comment
Здравствуйте, @Developer, я понимаю, что вашему вопросу уже почти год, но у меня похожая проблема, не могу заставить работать аннотацию RolesAllowed. Не могли бы вы сказать мне, нашли ли вы решение своей проблемы?   -  person PJvG    schedule 15.09.2014


Ответы (1)


Это немного устарело, но у меня все еще есть та же проблема (обратите внимание, что у меня также есть пользовательский 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").

person Derlin    schedule 12.07.2016