我正在按照以下答案:Best practice for REST token-based authentication with JAX-RS and Jersey来实现REST API身份验证。但是JAX-RS身份验证过滤器不是通过@Secured注释触发的。
我通过在方法上添加@Secured
来完成保护您的REST端点部分。
这就是我这样做的方式。
@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Secured { }
@Secured
@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
private static final String AUTHENTICATION_SCHEME = "Bearer";
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// Get the Authorization header from the request
String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
// Validate the Authorization header
if (!isTokenBasedAuthentication(authorizationHeader)) {
abortWithUnauthorized(requestContext);
return;
}
// Extract the token from the Authorization header
String token = authorizationHeader.substring(AUTHENTICATION_SCHEME.length()).trim();
try {
validateToken(token);
} catch (Exception e) {
abortWithUnauthorized(requestContext);
}
}
private boolean isTokenBasedAuthentication(String authorizationHeader) {
// Check if the Authorization header is valid
// It must not be null and must be prefixed with "Bearer" plus a whitespace
// Authentication scheme comparison must be case-insensitive
return (authorizationHeader != null &&
authorizationHeader.toLowerCase().startsWith(AUTHENTICATION_SCHEME.toLowerCase() + " "));
}
private void abortWithUnauthorized(ContainerRequestContext requestContext) {
// Abort the filter chain with a 401 status code
// The "WWW-Authenticate" is sent along with the response
requestContext.abortWith(
Response.status(Response.Status.UNAUTHORIZED)
.header(HttpHeaders.WWW_AUTHENTICATE, AUTHENTICATION_SCHEME)
.build());
}
private void validateToken(String token) throws Exception {
// Check if it was issued by the server and if it's not expired
// Throw an Exception if the token is invalid
}
@Path("api")
public class MyApis {
@GET
@Secured
@Path("me")
@Produces(MediaType.APPLICATION_JSON)
public Map<String, X500Name> whoAmI() {
return ImmutableMap.of("me", legalName);
}
// other APIs
}
当我拨打/api/me
时,我可以直接获得响应而不提供任何身份验证标头。似乎过滤器未被触发或未正确注册。
我已经看到了这个问题JAX RS, my filter is not working,但它并没有解决我的问题。
我理解以下内容是web.xml
不需要吗?
此解决方案仅使用JAX-RS 2.0 API,避免任何特定于供应商的解决方案。因此,它应该与最流行的JAX-RS 2.0实现一起使用,例如Jersey,RESTEasy和Apache CXF。
重要的是,如果您使用基于令牌的身份验证,则不依赖于servlet容器提供的标准Java EE Web应用程序安全机制,并且可以通过应用程序的web.xml描述符进行配置。
答案 0 :(得分:1)
最后一个答案,但是解决此问题的方法是将AuthenticationFilter添加到您的类中。
google.visualization.drawChart