Jax RS授权

时间:2016-08-14 21:32:57

标签: java web-services jax-rs restlet

我在类中的现有代码从javax.ws.rs.core.Application

扩展而来
...
Context childContext = component.getContext().createChildContext();
JaxRsApplication application = new JaxRsApplication(childContext);
application.add(this);
application.setStatusService(new ErrorStatusService());
childContext.getAttributes().put("My Server", this);
...

ChallengeAuthenticator challengeGuard = new ChallengeAuthenticator(null, ChallengeScheme.HTTP_BASIC, "REST API Realm");
//Create in-memory users with roles
MemoryRealm realm = new MemoryRealm();
User user = new User("user", "user");
realm.getUsers().add(user);
realm.map(user, Role.get(null, "user"));
User owner = new User("admin", "admin");
realm.getUsers().add(owner);
realm.map(owner, Role.get(null, "admin"));
//Attach verifier to check authentication and enroler to determine roles
challengeGuard.setVerifier(realm.getVerifier());
challengeGuard.setEnroler(realm.getEnroler());
challengeGuard.setNext(application);
// Attach the application with HTTP basic authentication security
component.getDefaultHost().attach(challengeGuard);

我的代码中没有web.xml。我想为我的代码添加授权。这个:https://restlet.com/technical-resources/restlet-framework/guide/2.3/core/security/authorization不适用于我,因为我没有restlet资源。

如何在我的代码中实现jax rs授权?

编辑1:现有代码使用restlet JAX-RS扩展:https://restlet.com/technical-resources/restlet-framework/guide/2.2/extensions/jaxrs

我在jax-rs资源类中试过了:

@GET
@Path("/")
public String getStatus() {
  if (!securityContext.isUserInRole("admin")) {
    throw new WebApplicationException(Response.Status.FORBIDDEN);
  }
  ...
}

然而,即使我使用admin用户登录,它也会引发403。

编辑2:

当我在这里查看时:https://restlet.com/technical-resources/restlet-framework/guide/2.2/extensions/jaxrs有一段代码:

this.setRoleChecker(...); // if needed

这可能会解决我的问题,但我不知道如何设置角色检查程序。

PS:我使用的是jersey 1.9和restlet 2.2.3。

3 个答案:

答案 0 :(得分:2)

它并不是很清楚(至少对我而言:-))你想要实现的目标。 如果你有一个类是javax.ws.rs.core.Application的子类,你应该能够简单地将@RolesAllowed(" user")作为注释添加到你的资源类中,如图所示https://jersey.java.net/documentation/latest/security.html

@Path("/")
@PermitAll
public class Resource {
    @RolesAllowed("user")
    @GET
    public String get() { return "GET"; }

    @RolesAllowed("admin")
    @POST
    public String post(String content) { return content; }

    @Path("sub")
    public SubResource getSubResource() {
        return new SubResource();
    }
}

访问该资源应提示您输入凭据。如果这不起作用,那么您需要提供一个小代码示例,它会编译并且不会执行您希望它执行的操作。然后,您可以更轻松地查看问题所在以及需要采取哪些措施才能使其正常工作

答案 1 :(得分:2)

我可以让它像那样工作:

申请类:

...
application.setRoles(getRoles(application));
... 
public static List<Role> getRoles(JaxRsApplication application) {
  List<Role> roles = new ArrayList<>();
  for (AuthorizationRoleEnum authorizationRole : AuthorizationRoleEnum.values()) {
      roles.add(new Role(application, authorizationRole.toString()));
  }
  return roles;
}
...

授权枚举:

public enum AuthorizationRoleEnum {
  USER("user"),
  ADMIN("admin");

  private final String value;

  AuthorizationRoleEnum(String value) {
    this.value = value;
  }

  @Override
  public String toString() {
    return value;
  }

}

在我的资源类中:

...
@Context
SecurityContext securityContext;
...
allowOnlyAdmin(securityContext);
...
public void allowOnlyAdmin(SecurityContext securityContext) {
  if (securityContext.getAuthenticationScheme() != null
    && !securityContext.isUserInRole(AuthorizationRoleEnum.ADMIN.toString())) {
    throw new WebApplicationException(Response.status(Response.Status.FORBIDDEN)
      .entity("User does not have required " + AuthorizationRoleEnum.ADMIN + " role!").build());
  }
}
...

答案 2 :(得分:0)

您需要实施RoleChecker using this interface。 正如医生所说:

  

由于Restlet API不支持自己的角色检查机制(例如Servlet API),因此如果需要在JAX-RS应用程序中进行角色检查,则必须使用此接口。   如果用户在角色中,则此接口用于检查。实现必须是线程保存。

作为实施的一个例子,你可以这样做:

  public class MyRoleChecker implements RoleChecker {
    public boolean isInRole(Principal principal, String role) {
      return principal.getRole().equals(role);
    } 
  }

编辑: 另一方面,当您使用新API时,需要实现SecurityContext并在资源方法中使用@Context注入它。 然后,您可以通过用户名从存储中获取角色列表。存储实现取决于您。请参阅此example

    @Priority(Priorities.AUTHENTICATION)
public class AuthFilterWithCustomSecurityContext implements ContainerRequestFilter {
    @Context
    UriInfo uriInfo;
    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        String authHeaderVal = requestContext.getHeaderString("Auth-Token");
        String subject = validateToken(authHeaderVal); //execute custom authentication
        if (subject!=null) {
            final SecurityContext securityContext = requestContext.getSecurityContext();
            requestContext.setSecurityContext(new SecurityContext() {
                        @Override
                        public Principal getUserPrincipal() {
                            return new Principal() {
                                @Override
                                public String getName() {
                                    return subject;
                                }
                            };
                        }
                        @Override
                        public boolean isUserInRole(String role) {
                            List<Role> roles = findUserRoles(subject);
                            return roles.contains(role);
                        }
                        @Override
                        public boolean isSecure() {
                            return uriInfo.getAbsolutePath().toString().startsWith("https");
                        }
                        @Override
                        public String getAuthenticationScheme() {
                            return "Token-Based-Auth-Scheme";
                        }
                    });
        }
    }
}