我尝试从java docs了解@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;
}
}
代理类。该类被注释为@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;
}
}
我创建了一个领域并添加了两个用户
用户A - 管理员, 用户B - 访客
如果没有 RunAs 注解,UserA 能够按预期访问该方法,而 UserB 无法按预期访问该方法。
当我添加 RunAs 注释后,两个用户都无法访问 getDetails 方法。
我认为 UserB 现在能够访问该方法,因为代理带有 RunAs admin 注释,并且我认为 StudentService 会将用户视为管理员角色。但事实上,UserA 也无法访问该方法。
谁能解释一下 RunAs 注释的重要性吗?
最佳答案
@RunAs 注释可用于 @Steve C 指出的用例,也可用于您所描述的用例。
您的代码和您的假设是正确的。它不起作用,因为某些容器(例如 Wildfly)默认实现 EJB 方法权限的方式。当根本不使用安全注释时,所有方法都被假定为未选中
,就好像它们使用@PermitAll进行注释一样。但是,当您的部署中使用任何安全注释并且方法没有显式权限(在类级别或方法级别)时,Wildfly 会将其视为具有 @DenyAll。
所以,您的 StudentService 是正确的,但在您的 StudentServiceProxy 中, getDetails 方法没有任何方法权限。您应该使用 @PermitAll (任何用户、未经身份验证的事件都可以执行它)、@RolesAllowed({ "**"}) (任何经过身份验证的用户都可以执行它)或 @RolesAllowed 注释它(在方法级别或类级别) ({ "admin", "guest"}) (具有管理员或访客角色的用户执行它)。
如果使用 wildfly/jboss,您还可以更改 ejb3 子系统的默认行为。检查:https://docs.jboss.org/author/display/WFLY/Securing+EJBs
关于java - @RunAs javax 安全注解有什么用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60206182/