我尝试了this教程并实现了示例中给出的Provider类。
@Provider
@Secured
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
private static final String REALM = "example";
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 {
// Validate the token
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
// The 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 response
// The WWW-Authenticate header is sent along with the response
requestContext.abortWith(
Response.status(Response.Status.UNAUTHORIZED)
.header(HttpHeaders.WWW_AUTHENTICATE,
AUTHENTICATION_SCHEME + " realm=\"" + REALM + "\"")
.build());
}
private void validateToken(String token) throws Exception {
// Check if the token was issued by the server and if it's not expired
// Throw an Exception if the token is invalid
//TODO validate against database
if(!token.equals("exampleString")) {
throw new AuthenticationException("Invalid token.");
}
}
}
服务器也可以识别此Provider类,可以在日志中看到:
Dez 25, 2017 6:47:09 PM com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFORMATION: Root resource classes found:
class com.jwt.service.AuthenticationEndpoint
class com.jwt.service.HelloWorldService
Dez 25, 2017 6:47:09 PM com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFORMATION: Provider classes found:
class com.jwt.service.AuthenticationFilter
我为注释创建了一个接口:
@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Secured {
}
还注释了我的REST端点。
@GET
@Path("/secured")
@Secured
public Response getUserSecured() {
return Response.status(200).entity("Secured getUser is called").build();
}
即使我的Provider类被识别,但在调用带注释的方法时它仍然没有做任何事情。即使没有发送身份验证,也不会输出未经授权的状态代码,而是返回“安全的getUser被调用”。
有人知道为什么我的Provider类的filter方法从未被调用过吗?
答案 0 :(得分:1)
com.sun.jersey.api
包(在提供的日志中可见)是Jersey 1,而您正在关注的教程涉及球衣2。
升级到泽西岛2,它将起作用。