2016-08-14 3 views
9

У меня есть существующий код в классе, который простирался от javax.ws.rs.core.ApplicationJax RS Авторизация

... 
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 не относится ко мне, так как у меня нет ресурсов перезагрузки.

Как я могу реализовать авторизацию jax rs в свой код?

EDIT 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); 
    } 
    ... 
} 

Однако, он выбрасывает 403 даже я войдите в систему с admin.

EDIT 2:

Когда я проверяю здесь: https://restlet.com/technical-resources/restlet-framework/guide/2.2/extensions/jaxrs Существует кусок кода:

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

Это может решить мою проблему, но я не знаю, как установить роль проверки ,

PS: Я использую джерси 1.9 и restlet 2.2.3.

ответ

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

Это не совсем понятно (по крайней мере для меня :-)), чего вы пытаетесь достичь. Если у вас есть класс, который является подклассом javax.ws.rs.core.Application, вы должны быть в состоянии просто добавить @RolesAllowed («пользователь») в качестве аннотации к классам ресурсов, как показано на 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(); 
    } 
} 

Доступ к этому ресурсу должен запрашивать ваши учетные данные. Если это не сработает, вам нужно предоставить небольшой образец кода, который компилирует и не делает того, что вы хотите. Тогда легче увидеть, где проблема, и что нужно сделать, чтобы она работала

+0

Я отредактировал свой вопрос. Ответ может быть очень простым, но я не мог найти способ заставить его работать. Я определяю роли через restlet (он использует расширение jax-rs), однако кажется, что он не распознается контекстом безопасности jax-rs. – kamaci

+0

Я сделал другое изменение, чтобы уточнить мой вопрос. – kamaci

+0

, если он дает вам ошибку 403, значит, это означает, что аутентификация работает :-) Вам просто нужно добавить пользователя в нужную группу. Это делается в конфигурации безопасности сервера приложений. Вы установили точку останова в первой строке в getStatus(), чтобы узнать, действительно ли она туда попала? – Guenther

0

Вам необходимо реализовать свой RoleCheckerusing this interface. Как док говорит:

Поскольку Restlet API не поддерживает свой собственный механизм для ролевых проверок (как, например, сервлет API), вы должны использовать эту inteface, если вам нужна роль проверка в применении в 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"; 
         } 
        }); 
     } 
    } 
} 
+0

Спасибо за ответ. Кажется разумным. Однако есть ли пример того, как его реализовать? – kamaci

+0

@kamaci Я отредактировал свой ответ, добавив пример реализации. –

+0

Я использую 'org.restlet.ext.jaxrs' версию 2.2.3, но похоже, что у него нет интерфейса с именем« RoleChecker »? – kamaci