如何在Jersey中验证用户身份

我正在使用Jersey在Java中编写RESTful应用程序,我需要对用户进行身份验证.我知道我可以使用注释@RolesAllowed在资源中指定角色,但我无法理解用户如何与特定角色相关联.客户端以这种方式发送用户名和密码

    HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic(user, password);
    Client client = ClientBuilder.newClient();
    client.register(feature);
    WebTarget target = client.target(baseUrl).path(urlString);
    Invocation.Builder invocationBuilder = target.request(MediaType.APPLICATION_JSON);
    Response response = invocationBuilder.get();

假设某些方法只能由超级用户和其他用户使用,当客户端发送用户名和密码时,如何区分它们?

解决方法:

I know i can specify the roles in the resource using the annotations @RolesAllowed, but i can’t understand how a user is associated to a specific role

角色信息存储在DB中.假设您有一个用户在数据库中为USER和ROLES表建模

class User {
  String username;
  List<String> roles;

  public String getUsername() { return username; }
  public void setUsername(String username) { this.username = username; }
  public List<String> getRoles() { return roles; }
  public void setRoles(List<String> roles) { this.roles = roles; }
}

您可以在泽西过滤器中获得用户.这也是您要进行身份验证的地方.

@Provider
@Priority(Priorities.AUTHENTICATION)  // needs to happen before authorization
class AuthenticationFilter implements ContainerRequestFilter {
    @Inject
    private UserService userService;  // this is your own service

    @Override
    public void filter(ContainerRequestFilter filter) {
        // note, this is a lazy implementation of Basic auth.
        // it doesn't do ant error checking. Please see
        // link at bottom for better imlementation
        String authzHeader = filter.getHeaderString(HttpHeaders.AUTHORIZATION); // (1)
        String decoded = Base64.decodeAsString(authzHeader);
        String[] split = decoded.split(":");
        User user = userService.getUser(split[0]);                              // (2)
        if (user == null || !user.getPassword().equals(someHash(split[1])) {    // (3)
            throw new UnauthorizedException();
        }
        SecurityContext oldContext = filter.getSecurityContext();               // (4)
        filter.setSecurityContext(new BasicSecurityConext(user, oldContext.isSecure()));
    }
}

你在这做的是:

>解析Basic Auth Authorization标头
>使用用户名获取用户
>进行身份验证
>设置新的SecurityContext.

BasicSecurityContext如下所示.您可以在此处将角色与用户关联.

static class BasicSecurityContext implements SecurityContext {
   private final User user;
   private final boolean secure;

   public BasicSecurityContext(User user, boolean secure) {
       this.user = user;
       this.secure = secure;
   }

   @Override
   public Principal getUserPrincipal() {
       return new Principal() {
           @Override
           public String getName() {
                return user.getUsername();
           }
       };
   }

   @Override
   public String getAuthenticationScheme() {
       return SecurityContext.BASIC_AUTH;
   }

   @Override
   public boolean isSecure() { return secure; }

   @Override
   public boolean isUserInRole(String role) {
       return user.getRoles().contains(role);
   }
}

如果你看一下isUserInRole的底部.会发生什么是Jersey将从资源方法或类中获取@RolesAllowed注释,获取值,然后将它们传递给isUserInRole.如果返回true,则授权用户.在伪代码中

@RolesAllowed({"USER", "SUPER_USER"})
public Response get() {}
...

RolesAllowed annotation = resourceMethod.getAnnotation(RolesAllowed.class);
String roles = annotation.value();
SecurityContext context = getSecurityContext();
for (String role: roles) {
    if (context.isUserInRole(role)) {
        return;
    }
}
throw new ForbiddenException();

这只是伪代码,但它显示了Jersey如何使用@RolesAllowed,SecurityContext以及如何实现isUserInRole来处理授权.

此授权功能不会自动打开.你需要自己打开它.为此,只需注册RolesAllowedDynamicFeature即可

public JerseyConfig extends ResourceConfig {
    public JerseyConfig() {
        register(RolesAllowedDynamicFeature.class);
    }
}

这里要注意的一点是,在上述所有内容中,我们正在实现基本身份验证和安全上下文的设置.这没有什么不妥.但是如果你使用servlet容器认证机制,Jersey实际上将从HttpServletRequest获取auth信息. HttpServletRequest有一个getUserPrincipal()方法和一个isUserInRole方法. Jersey将使用这些来委托SecurityContext.因此,如果您是用户容器身份验证,那么您实际上并不需要实现任何东西.您只需要注册RolesAllowedDynamicFeature

如果要使用容器的身份验证机制,则应查阅服务器的文档.在您的服务器中设置了一个领域之后,您将需要使用安全信息配置web.xml.下面的链接中有一个例子.您还应该在Web安全性部分的Java EE文档中找到此信息.

也可以看看:

> Filter and Interceptors了解有关使用过滤器的更多信息.
> Security获取有关在泽西岛使用安全性的更多信息.
> A better implementation of the basic auth filter

上一篇:java – 在Grizzly上使用JaaS和Jersey


下一篇:java – Jersey-请求身份验证