我使用JAX-RS,Jersey和Grizzly编写了一个简单的REST服务器。这就是我启动服务器的方式:
URI baseUri = UriBuilder.fromUri("http://localhost/api")
.port(8081)
.build();
ResourceConfig rc = new PackagesResourceConfig("se.aioobe.resources");
HttpServer httpServer = GrizzlyServerFactory.createHttpServer(baseUri, rc);
现在我需要使用基本HTTP身份验证来保护资源,我无法弄清楚如何执行此操作。
我可以从Grizzly切换到例如Jetty,如果它更容易让它工作,但我真的很重视Grizzly提供的简单配置/启动。
我已经阅读了很多教程。他们都提到了web.xml,但在我目前的配置中我没有。 (我是否需要为HTTP身份验证添加一个?)我找到了following questions,它们都没有任何帮助: - (
(此时不需要SSL。此时的身份验证只是为了防止公众在我们的测试版中偷看。)
TL; DR :如何向Jersey / Grizzly webapp添加基本HTTP身份验证?
答案 0 :(得分:9)
根据this blog post,我设法让它在几个小时后运行。
我的解决方案涉及:
我创建了这个ContainerRequestFilter
:
public class AuthFilter implements ContainerRequestFilter {
// Exception thrown if user is unauthorized.
private final static WebApplicationException unauthorized =
new WebApplicationException(
Response.status(Status.UNAUTHORIZED)
.header(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"realm\"")
.entity("Page requires login.").build());
@Override
public ContainerRequest filter(ContainerRequest containerRequest)
throws WebApplicationException {
// Automatically allow certain requests.
String method = containerRequest.getMethod();
String path = containerRequest.getPath(true);
if (method.equals("GET") && path.equals("application.wadl"))
return containerRequest;
// Get the authentication passed in HTTP headers parameters
String auth = containerRequest.getHeaderValue("authorization");
if (auth == null)
throw unauthorized;
auth = auth.replaceFirst("[Bb]asic ", "");
String userColonPass = Base64.base64Decode(auth);
if (!userColonPass.equals("admin:toHah1ooMeor6Oht"))
throw unauthorized;
return containerRequest;
}
}
然后我更改了启动代码以包含过滤器:
URI baseUri = UriBuilder.fromUri("http://localhost/api")
.port(8081)
.build();
ResourceConfig rc = new PackagesResourceConfig("se.aioobe.resources");
// Add AuthFilter ////////////
rc.getProperties().put("com.sun.jersey.spi.container.ContainerRequestFilters",
"<YOUR PACKAGE FOR AuthFilter>.AuthFilter");
//////////////////////////////
HttpServer httpServer = GrizzlyServerFactory.createHttpServer(baseUri, rc);
答案 1 :(得分:4)
您可能需要检查与泽西岛一起分发的HTTPS客户端服务器Grizzly sample。以下是该示例中关于在Grizzly服务器上配置安全过滤器的要点。
WebappContext context = new WebappContext("context");
ServletRegistration registration =
context.addServlet("ServletContainer", ServletContainer.class);
registration.setInitParameter("com.sun.jersey.config.property.packages",
"com.sun.jersey.samples.https_grizzly.resource;com.sun.jersey.samples.https_grizzly.auth");
// add security filter (which handles http basic authentication)
registration.setInitParameter(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS,
"com.sun.jersey.samples.https_grizzly.auth.SecurityFilter;com.sun.jersey.api.container.filter.LoggingFilter");
registration.setInitParameter(ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS,
LoggingFilter.class.getName());
try {
webServer = GrizzlyServerFactory.createHttpServer(
getBaseURI()
);
// start Grizzly embedded server //
System.out.println("Jersey app started. Try out " + BASE_URI + "\nHit CTRL + C to stop it...");
context.deploy(webServer);
webServer.start();
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
您正在注册一个SecurityFilter,它负责您的HTTP基本身份验证。在服务器上启用日志记录筛选器应在请求中显示基本身份验证标头。这是一个例子:
Jan 30, 2013 8:59:00 PM com.sun.jersey.api.container.filter.LoggingFilter filter
INFO: 1 * Server in-bound request
1 > GET http://localhost:8080/context/
1 > host: localhost:8080
1 > connection: keep-alive
1 > cache-control: max-age=0
1 > authorization: Basic dXNlcjpwYXNzd29yZA==
1 > accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
1 > user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17
1 > accept-encoding: gzip,deflate,sdch
1 > accept-language: en-US,en;q=0.8
1 > accept-charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
1 >
Service: GET / User: user
Jan 30, 2013 8:59:00 PM com.sun.jersey.api.container.filter.LoggingFilter$Adapter finish
INFO: 1 * Server out-bound response
1 < 200
1 < Content-Type: text/html
1 <
JERSEY HTTPS EXAMPLE
答案 2 :(得分:1)
@aioobe请注意,虽然这样做很有意义,但在使用标题时需要更好的错误检查。例如:
auth = auth.replaceFirst("[Bb]asic ", "");
这假设认证头是Basic,而它可能不是。您应检查授权标头是否以“基本”开头,如果没有未经授权,则应检查。同样的事情是确保其余的信息实际上是base64编码的。