Какая польза от аннотации безопасности javax @RunAs?

Я попытался понять использование аннотации @RunAs из java docs, но я не понял его использования. Кто-нибудь может объяснить?

Я понимаю, что в некоторых случаях, если аутентифицированный пользователь с другой ролью хочет получить доступ к методу ejb, доступ к которому разрешен только пользователям с определенными ролями, тогда вызывающий ejb может аннотировать себя для запуска как ожидается роль и может получить доступ к методу ejb.

Итак, я написал приведенный ниже код, но мое понимание неверно.

JAX-RS Класс:

package com.jee.beginner.rest;

import java.security.Principal;

import javax.inject.Inject;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.groups.ConvertGroup;
import javax.validation.groups.Default;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;

import com.jee.beginner.custom.validation.Create;
import com.jee.beginner.custom.validation.Update;
import com.jee.beginner.domain.Student;
import com.jee.beginner.service.StudentService;
import com.jee.beginner.service.proxy.StudentServiceProxy;

@Path("student")
public class StudentResource {

    @Inject
    private Principal principal;

    @Inject
    private StudentService studentService;

    @Inject
    private StudentServiceProxy studentServiceProxy;

    @GET
    @Path("details/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Student getDetails(@PathParam("id") @Min(value = 2, message = "ID cannot be less than 2") int id,
            @QueryParam("id") int qid, @Context UriInfo uriInfo) {

        return studentServiceProxy.getDetails(id);
    }

    @POST
    @Path("new")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Student addStudent(@Valid @ConvertGroup(from = Default.class, to = Create.class) final Student student) {

        return studentService.addStudent(student);
    }

    @POST
    @Path("update")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Student updateStudent(@Valid @ConvertGroup(from = Default.class, to = Update.class) final Student student) {

        return student;
    }
}

Прокси-класс. Этот класс помечен как @RunAs("admin")

package com.jee.beginner.service.proxy;

import javax.annotation.security.RunAs;
import javax.ejb.Stateless;
import javax.inject.Inject;

import com.jee.beginner.domain.Student;
import com.jee.beginner.service.StudentService;

@RunAs("admin")
@Stateless
public class StudentServiceProxy {

    @Inject
    private StudentService studentService;

    public Student getDetails(int id) {
        return studentService.getDetails(id);
    }
}

Класс обслуживания:

package com.jee.beginner.service;

import javax.annotation.Resource;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJBContext;
import javax.ejb.Stateless;

import com.jee.beginner.domain.Student;

@Stateless
public class StudentService {

    @Resource
    private EJBContext context;

    @RolesAllowed({ "admin", "guest" })
    public Student addStudent(final Student student) {
        System.out.println(context.isCallerInRole("admin"));
        return student;
    }

    @RolesAllowed({ "admin" })
    public Student getDetails(int id) {
        Student student = new Student();
        student.setId(id);
        student.setName("noname");
        return student;
    }
}

Я создал область и добавил двух пользователей

Пользователь А - админ, пользователь Б - гость

Без аннотации RunAs пользователь A смог получить доступ к методу, как ожидалось, а пользователь B не смог получить доступ к методу, как ожидалось.

Как только я добавил аннотацию RunAs, оба пользователя не смогли получить доступ к методу getDetails.

Я думал, что UserB сможет получить доступ к методу сейчас, потому что прокси-сервер аннотирован администратором RunAs, и я думал, что StudentService будет рассматривать пользователя как роль администратора. Но на самом деле произошло то, что UserA также не смог получить доступ к методу.

Может ли кто-нибудь объяснить мне значение аннотации RunAs?


person Krishna Chaitanya    schedule 13.02.2020    source источник


Ответы (2)


Аннотация @RunAs может использоваться для вариантов использования, на которые указывает @Steve C, но также и для точного варианта использования, который вы описываете.

Ваш код и ваши предположения верны. Это не работает, потому что некоторые контейнеры (например, Wildfly) реализуют разрешения метода EJB по умолчанию. Когда аннотации безопасности вообще не используются, все методы считаются unchecked, как если бы они были аннотированы @PermitAll. Но когда в вашем развертывании используется какая-либо аннотация безопасности, а метод не имеет явных разрешений (на уровне класса или на уровне метода), Wildfly обрабатывает его так, как если бы у них был @DenyAll.

Итак, ваш StudentService правильный, но в вашем StudentServiceProxy метод getDetails не имеет разрешения на какой-либо метод. Вы должны аннотировать его (на уровне метода или класса) с помощью @PermitAll (любой пользователь, событие, не прошедшее проверку подлинности, может выполнить его), @RolesAllowed({ "**" }) (любой аутентифицированный пользователь может выполнить его) или @RolesAllowed ({ "admin", "guest" }) (пользователи с ролью администратора или гостя выполняют его).

При использовании wildfly/jboss вы также можете изменить поведение по умолчанию подсистемы ejb3. Проверьте: https://docs.jboss.org/author/display/WFLY/Securing+EJBs

person areus    schedule 29.02.2020

Обычно метод EJB вызывается синхронно в результате некоторого действия аутентифицированного пользователя. Сервер приложений распространяет контекст безопасности пользователя вместе с вызовом, и контейнер EJB может использовать этот контекст для проверки того, что вызывающий объект связан с разрешенными ролями для этого метода.

Однако бывают ситуации, когда метод EJB может быть вызван без участия аутентифицированного пользователя. К таким ситуациям относятся:

  • выполнение таймера EJB
  • выполнение bean-компонента, управляемого сообщениями (MDB)

Например, вы можете определить периодическую службу, которая должна выполняться:

@Stateless
public class StudentService {

     @Timeout
     @Schedule(...)
     @RunAs("admin")
     public void periodicCheck(Timer timer) {
         ...
     }

}

Использование javax.annotation.security.RunAs здесь означает, что этот метод должен выполняться с ролью «admin».

person Steve C    schedule 29.02.2020