@runasjavax安全注释的用途是什么?

@runasjavax安全注释的用途是什么?,java,ejb,java-security,Java,Ejb,Java Security,我试图从中理解@RunAs注释的用法,但我不理解它的用法。谁能解释一下吗 我的理解是,在某些情况下,如果具有不同角色的经过身份验证的用户希望访问仅允许具有特定角色的用户访问的ejb方法,那么调用方ejb可以将自身注释为作为预期角色运行,并可以访问ejb方法 所以我写了下面的代码,但我的理解是错误的 JAX-RS类: package com.jee.beginner.rest; import java.security.Principal; import javax.inject.Inject

我试图从中理解@RunAs注释的用法,但我不理解它的用法。谁能解释一下吗

我的理解是,在某些情况下,如果具有不同角色的经过身份验证的用户希望访问仅允许具有特定角色的用户访问的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;
    }
}
代理类。此类被注释为@RunAsadmin

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, 用户B-来宾

没有RunAs注释,UserA能够按预期访问该方法,而UserB不能按预期访问该方法

我一添加RunAs注释,两个用户就无法访问getDetails方法

我认为UserB现在可以访问该方法,因为代理使用RunAs admin进行注释,并且我认为StudentService会将用户视为admin角色。但事实上,UserA也无法访问该方法


有人能给我解释一下RunAs注释的意义吗?

通常,经过身份验证的用户的某些操作会同步调用EJB方法。应用服务器传播用户的安全上下文以及调用,EJB容器可以使用该上下文验证调用方是否与该方法允许的角色关联

但是,在某些情况下,可以在没有经过身份验证的用户参与的情况下调用EJB方法。这些情况包括:

EJB计时器的执行 消息驱动bean MDB的执行 例如,您可能已定义了应执行的定期服务:

@Stateless
public class StudentService {

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

}

使用here表示此方法应使用admin角色执行。

通常,经过身份验证的用户执行某些操作后,将同步调用EJB方法。应用服务器传播用户的安全上下文以及调用,EJB容器可以使用该上下文验证调用方是否与该方法允许的角色关联

但是,在某些情况下,可以在没有经过身份验证的用户参与的情况下调用EJB方法。这些情况包括:

EJB计时器的执行 消息驱动bean MDB的执行 例如,您可能已定义了应执行的定期服务:

@Stateless
public class StudentService {

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

}

使用here表示此方法应与admin角色一起执行。

可以将@RunAs注释用于@Steve C指出的用例,也可以用于您正在描述的用例

您的代码和假设是正确的。它不起作用,因为某些容器(例如Wildfly)默认实现EJB方法权限的方式。如果根本不使用安全注释,则假定所有方法都未选中,就好像它们在何处用@PermitAll注释一样。但是,如果在部署中使用了任何安全注释,并且方法在类级别或方法级别没有显式权限,则Wildfly会将其视为具有@DenyAll

因此,StudentService是正确的,但是在StudentServiceProxy中,getDetails方法没有任何方法权限。您应该在方法级别或类级别使用@PermitAll any user注释它,未经验证的事件可以执行它,@RolesAllowed{**}任何经过身份验证的用户都可以执行它,或者使用admin或guest角色的@RolesAllowed{admin,guest}用户可以执行它


如果使用wildfly/jboss,还可以更改ejb3子系统的默认行为。检查:

运行方式注释可以用于@Steve C指出的用例,也可以用于您正在描述的用例

您的代码和假设是正确的。它不起作用,因为某些容器(例如Wildfly)默认实现EJB方法权限的方式。如果根本不使用安全注释,则假定所有方法都未选中,就好像它们在何处用@PermitAll注释一样。但是,如果在部署中使用了任何安全注释,并且方法在类级别或方法级别没有显式权限,则Wildfly会将其视为具有@DenyAll

因此,StudentService是正确的,但是在StudentServiceProxy中,getDetails方法没有任何方法权限。您应该在方法级别或类级别使用@PermitAll any user注释它,未经验证的事件可以执行它,@RolesAllowed{**}任何经过身份验证的用户都可以执行它,或者使用admin或guest角色的@RolesAllowed{admin,guest}用户可以执行它

如果使用wildfly/jboss,还可以更改ejb3子系统的默认行为。检查: