【问题标题】:Set roles in Jersey web service在 Jersey Web 服务中设置角色
【发布时间】:2016-09-14 10:35:00
【问题描述】:

我正在使用 Jersey + Jetty + Dropwizard + Hibernate 创建一个 Web 服务。

假设我有一个这样的网络资源:

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

我知道您可以使用HttpServletRequest.isUserInRole 检查用户的角色。

问题是,我如何分配角色开始? Jersey 如何知道 isUserInRole 方法返回什么,或者知道如何根据角色过滤人们不访问特定资源?

我没有web.xmlwebdefault.xml,所以应该在其他地方进行定义。

【问题讨论】:

  • 您查看过Dropwizard Auth 的文档吗?它支持基本和 OAuth。还有第三方lib for JWT。所有这些角色的东西都由框架处理。除非你有并且这些解决方案都不适合你,并且你想自己动手

标签: java jersey jetty dropwizard


【解决方案1】:

您必须提供一个支持 @RolesAllowed("admin") 注释的提供程序类,然后您必须在您的应用程序中注册提供程序类。通常它在 web.xml 中完成,但由于您没有使用它,您必须自己提供。相关示例可以找到here

【讨论】:

  • 这个例子包括在我说我没有的 web.xml 文件中进行设置
  • 那么你是如何加载你的 jersey servlet 的。你必须使用一些配置文件或注释(@webservlet)。你必须在那里加载它。
  • 我得到了一个config.yml文件,所有的资源配置等都是通过dropwizard的配置类完成的
  • 或者更准确地说,是一个使用配置对象初始化的dropwizard的应用程序类
【解决方案2】:

Jersey 使用自己的机制来检查角色(参见SecurityContext 接口),但是如果没有明确设置,它会回退到容器身份验证,这通常使用 JaaS 实现。如果你有web.xml,你就可以在那里配置它的基础知识。

然后又经常以不同的方式进行身份验证。如果您可以手动登录用户,例如有一个可以检查名称/密码的服务,那么您可以实现一个 ContainerRequestFilter 来填充安全上下文,这将使 @RolesAllowed 注释正常工作。

例如:

根据 cmets 更新

Resouce方法登录用户:

@Path("some/login/path")
public void login() {
    String name = getUsernameFromRequest();
    String password = // like above
    User user = loginService.login(name, password);
    request.getSession().addAttribute("user", user);
}

在过滤器中为所有请求初始化安全上下文。

@Priority(Priorities.AUTHENTICATION)
public class JerseySecurityContextFilter implements ContainerRequestFilter {

    public void filter(final ContainerRequestContext context) throws IOException {
    User user = getUserFromSession();
    if (user != null) {
         // this sets security context for the rest of processing
         // it should make @RolesAllowed work
         context.setSecurityContext(new JerseySecurityContext(user);
    }
}

final class JerseySecurityContext implements SecurityContext {

    private final User user;

    public JerseySecurityContext(final User user) {
        this.user = user;
    }

    public boolean isUserInRole(final String roleName) {
        return user.hasRole(roleName);
    }

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

    public String getAuthenticationScheme() {
        return null;
    }
}

如果您更愿意使用 JaaS,那么您必须在应用程序配置中配置安全性。这些是嵌入式Jetty 的一些示例。

【讨论】:

  • 现在我得到了一个名为 loginUser 的资源方法,它获取用户名和密码并检查它是否与数据库中的匹配。当调用这个特定的资源类时,我如何告诉这个 JerseySecurityContextFilter 运行?
  • 当用户登录并运行您的资源方法时,创建一个会话并将用户放入其中。然后过滤器将能够检查用户是否存在于会话中。如果是,他已登录,如果不是,他未登录。您可以使用几种方法将过滤器添加到球衣。其中之一是使用ResourceConfig 注册过滤器类。
  • 我现在意识到我在过滤器中建议登录用户有点误导了你。如果您使用基本身份验证之类的东西,那很好。如果您使用具有登录方法的资源支持的专用表单或类似的东西,请将用户对象放入会话中,然后将其从过滤器中的会话中拉出。其余的可以保持不变。如果您愿意,我可以更新代码示例。
猜你喜欢
  • 2015-03-09
  • 2014-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-13
  • 2015-11-19
  • 2014-08-22
相关资源
最近更新 更多