我试图从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;
}
}
我创建了一个领域并添加了两个用户
UserA-管理员,UserB-客人
没有RunAs批注,UserA可以按预期访问方法,而UserB不能按预期访问方法。
我添加了RunAs批注后,两个用户都无法访问getDetails方法。
我以为UserB现在可以访问该方法,因为Proxy带有RunAs admin注释,我认为StudentService会将用户视为admin角色。但是实际上发生的是UserA也无法访问该方法。
任何人都可以向我解释RunAs注释的重要性吗?
通常,经过身份验证的用户通过某种操作将同步调用EJB方法。应用程序服务器将用户的安全上下文与调用一起传播,并且EJB容器可以使用此上下文来验证调用方是否与该方法的允许角色相关联。
但是,在某些情况下,可以在没有经过身份验证的用户参与的情况下调用EJB方法。这些情况包括:
例如,您可能已经定义了应该执行的定期服务:
@Stateless
public class StudentService {
@Timeout
@Schedule(...)
@RunAs("admin")
public void periodicCheck(Timer timer) {
...
}
}
此处使用javax.annotation.security.RunAs表示此方法应以“ admin”角色执行。