gpt4 book ai didi

java - 有没有办法根据用户的角色和@RolesAllowed 获取用户有权访问的所有 Jersey 网址的列表?

转载 作者:行者123 更新时间:2023-12-02 06:14:05 26 4
gpt4 key购买 nike

我希望向客户端提供休息 API 调用(通过普通 Jersey ,而不是 spring),以根据他们在 header 中发送的 JWT 返回特定用户允许的所有端点的列表。我在 stackoverflow(感谢贡献者!)示例代码中找到了获取所有端点的示例代码,无论角色如何,但不是基于角色的子集。我也找到了如何获取每个方法的注释,但希望避免重新发明“if @PermitAll 而不是 @DenyAll,或 RolesAllowed 中的角色等......”的轮子。

Jersey 2.0 是否有一个我可以调用的方法,该方法将在给定 SecurityContext 和 url 端点或方法的情况下解析为 true/false?

boolean allowed = isMethodAllowed(SecurityContext ctx, String url);

或者

boolean allowed = isMethodAllowed(SecurityContext ctx, 类方法);

最佳答案

感谢这篇文章:Listing all deployed rest endpoints (spring-boot, jersey)

特别是 Johanne Jander 的帖子(谢谢!),我想出了下面的代码,它似乎适用于我的情况,一个简单的 Jersey 用例。在此提供,以防对其他人有用。

@Path("/v1/userinterface")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public class MyUI extends MyRestApi {

private final static Logger log = LoggerFactory.getLogger(MyUI.class);

@Context
private Configuration configuration;

@Context
private SecurityContext security;

@Path("/allowedendpoints")
@GET
@Operation(summary = "List API access points allowed for the currently authenticated user", tags = {
"ui" }, description = "Returns a list of urls", responses = {})
public Response showAll(@Context UriInfo ui) {

log.debug("Get list of all allowed endpoints for user: " + security.getUserPrincipal().getName());

HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();

for (Class<?> c : configuration.getClasses()) {
// Since all of my endpoint classes extend MyRestApi,
// only scan them, not all classes
if (MyRestApi.class.isAssignableFrom(c)) {
scanClass(c, map);
}
}

return Response.ok().entity(map).build();
}

public void scanClass(Class<?> baseClass, HashMap<String, ArrayList<String>> map) {
Builder builder = Resource.builder(baseClass);
if (null != builder) {
Resource resource = builder.build();
String uriPrefix = "";
process(uriPrefix, resource, map);
}
}

private void process(String uriPrefix, Resource resource, HashMap<String, ArrayList<String>> map) {

// recursive method

String pathPrefix = uriPrefix;
List<Resource> resources = new ArrayList<>();
resources.addAll(resource.getChildResources());

if (resource.getPath() != null) {
pathPrefix = (pathPrefix + "/" + resource.getPath()).replaceAll("//", "/");
}

for (ResourceMethod method : resource.getAllMethods()) {
if (method.getType().equals(ResourceMethod.JaxrsType.SUB_RESOURCE_LOCATOR)) {
resources.add(Resource
.from(resource.getResourceLocator().getInvocable().getDefinitionMethod().getReturnType()));
} else {
if (isPathAllowed(security, method.getInvocable().getDefinitionMethod())) {
if (map.containsKey(pathPrefix))
map.get(pathPrefix).add(method.getHttpMethod());
else
map.put(pathPrefix, new ArrayList<String>(Arrays.asList(method.getHttpMethod())));
}
}
}

for (Resource childResource : resources) {
process(pathPrefix, childResource, map);
}
}

public boolean isPathAllowed(SecurityContext ctx, Method method) {

// @DenyAll on the method takes precedence over @RolesAllowed and @PermitAll
if (method.isAnnotationPresent(DenyAll.class)) {
return (false);
}

// @RolesAllowed on the method takes precedence over @PermitAll
RolesAllowed rolesAllowed = method.getAnnotation(RolesAllowed.class);
if (rolesAllowed != null) {
return (hasRole(ctx, rolesAllowed.value()));
}

// @PermitAll on the method takes precedence over @RolesAllowed on the class
if (method.isAnnotationPresent(PermitAll.class)) {
return (true);
}

// @DenyAll can't be attached to classes

// @RolesAllowed on the class takes precedence over @PermitAll on the class
rolesAllowed = method.getDeclaringClass().getAnnotation(RolesAllowed.class);
if (rolesAllowed != null) {
return (hasRole(ctx, rolesAllowed.value()));
}

// @PermitAll on the class
if (method.getDeclaringClass().isAnnotationPresent(PermitAll.class)) {
return (true);
}

return (false); // default
}

private boolean hasRole(SecurityContext ctx, String[] rolesAllowed) {

for (final String role : rolesAllowed) {
if (ctx.isUserInRole(role)) {
return (true);
}
}

return (false);
}

它根据带有 @DenyAll、@PermitAll 和 @RolesAllowed 注释的 SecurityContext 标记返回当前经过身份验证的用户有权访问的端点。

完全公开,我的应用程序很简单,在端点处只有基本的类和方法注释。 ymmv。

示例输出:

{
"/v1/resources" : [
"POST",
"GET"
],
"/v1/resources/{id}" : [
"DELETE",
"GET"
]
}

关于java - 有没有办法根据用户的角色和@RolesAllowed 获取用户有权访问的所有 Jersey 网址的列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55882717/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com