如何验证Jersey中的用户 [英] How to authenticate users in Jersey

查看:103
本文介绍了如何验证Jersey中的用户的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am writing a RESTful application in Java using Jersey, and i need to authenticate users. 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. The client sends username and password in this way

    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();

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

Supposing that some methods can be used only by superusers and others by any user, how can i distinguish them when the username and the password are sent by the client?

推荐答案


我知道我可以指定使用注释@RolesAllowed在资源中的角色,但我无法理解用户如何与特定角色相关联

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表建模

The role information is stored in the DB. Assuming say you have a User that models the USER and ROLES table in the DB

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; }
}

你会得到用户在泽西过滤器内。这也是您要进行身份验证的地方。

You would get the User inside a Jersey filter. This is also where you would authenticate.

@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()));
    }
}

你在这里做的是:


  1. 解析基本身份验证授权标头

  2. 使用用户名<获取用户 / li>
  3. 进行身份验证

  4. 设置新的 SecurityContext

  1. Parsing the Basic Auth Authorization header
  2. Getting the User with the username
  3. Doing your authentication
  4. Setting a new SecurityContext.

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

The BasicSecurityContext is shown below. This is where you will associate roles with the user.

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

如果你看看<$ c的底部$ C>的isUserInRole 。会发生什么事情,泽西岛将从资源方法或类中获取 @RolesAllowed 注释,获取值,然后将它们传递给 isUserInRole 。如果它返回 true ,则用户被授权。在伪代码中

If you look at the bottom at the isUserInRole. What will happen is that Jersey will grab the @RolesAllowed annotation from the resource method or class, grab the values, then pass them to the isUserInRole. If it returns true, then the user is authorized. In pseudo-code

@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

This is just pseudo-code, but it shows how Jersey handles the authorizaiton, using the @RolesAllowed, the SecurityContext, and how you implement the isUserInRole.

此授权功能不会自动启用。你需要自己打开它。为此,只需注册 RolesAllowedDynamicFeature

This authorization feature is not automatically turned on. You need to turn it on yourself. To do so, simply register the RolesAllowedDynamicFeature

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

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

One thing to note here is that in all of the above, we are implementing our basic authentication and setting of the security context. There is nothing really wrong with this. But if you are using the servlet container authentication mechanism, Jersey will actually take the auth information from the HttpServletRequest. The HttpServletRequest has a getUserPrincipal() method and a isUserInRole method. Jersey will use these to delegate in the SecurityContext. So if you are user the container authentication, then you don't really need to implement anything. You just need to register the RolesAllowedDynamicFeature

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

If you want to use your container's authentication mechanism, you should consult your server's documentation. After having set up a realm in with your server, you will then need to configure the web.xml with the security information. There's an example in the link below. You should also find this information in the Java EE docs under the web security section.

另请参阅:

  • Filter and Interceptors to learn more about working with filters.
  • Security for a little more info on working with security in Jersey.
  • A better implementation of the basic auth filter

这篇关于如何验证Jersey中的用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆