Какая польза от аннотации безопасности @RunAs javax? - PullRequest
0 голосов
/ 13 февраля 2020

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

Что я понимаю, в некоторых случаях, если аутентифицированный пользователь с другой ролью хочет получить доступ к методу 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;
    }
}

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

UserA - admin , UserB - guest

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

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

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

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

Ответы [ 2 ]

2 голосов
/ 29 февраля 2020

Аннотация @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

2 голосов
/ 29 февраля 2020

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

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

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

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

@Stateless
public class StudentService {

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

}

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

...