Java

时间:2019-04-07 13:04:52

标签: java java-ee jwt jax-rs restful-authentication

我正在尝试实现某种基于角色的身份验证。我正在使用JWT令牌。我一直在寻找指南,但是所有指南都提到了“ Spring boot”的使用。如何在Java的宁静端点上设置基于角色的身份验证?最好通过某种过滤器。

我正在寻找一种在端点之前简单添加:@Role(Role.ADMIN)的方法。

我已经设置了以下课程:

  • 枚举角色:

    public enum Role {
        User,
        Admin
    }
    
  • 简单的JWT令牌:

    {
     "sub": "users/TzMUocMF4p",
     "exp": 1554646441,
     "username": "username@gmail.com",
     "ID": 6,
     "Role": "Admin",
     "iat": 1554641041
    }
    
  • 简单的CRUD端点

    @Path("User")
    public class UserResource {
    
       @EJB
       private UserDAO userappDAO;
    
    
       @GET
       @JWTTokenNeeded
       @Produces("application/json")
       public List<Userapp> all() {
           return userappDAO.getAll();
       }
    }
    
  • JWT验证(@JWTTokenNeeded)以下类:

    @javax.ws.rs.NameBinding
    @Retention(RUNTIME)
    @Target({TYPE, METHOD})
    public @interface JWTTokenNeeded {
    }
    

    实际过滤器:

    @Provider
    @JWTTokenNeeded
    @Priority(Priorities.AUTHENTICATION)
    public class JWTTokenNeededFilter implements ContainerRequestFilter {
    
    
        @Override
        public void filter(ContainerRequestContext requestContext) throws IOException {
    
    // Get the HTTP Authorization header from the request
    String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
    
    try {
        // Extract the token from the HTTP Authorization header
        String token = authorizationHeader.substring("Bearer".length()).trim();
        // Validate the token
        Jwts.parser().setSigningKey("MYSECRET".getBytes("UTF-8")).parseClaimsJws(token);
    
    }
    catch (Exception e) {
        requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
    }
    }
    }
    

如果未授权用户,我想退出: requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());

如果用户获得了授权,则端点必须这样做。

1 个答案:

答案 0 :(得分:1)

我找到了可行的解决方案。它包括向@JWTTokenNeeded界面和JWTTokenNeededFilter类添加几行。

我最终得到了以下代码:

JWTTokenNeededFilter:

@Provider
@JWTTokenNeeded
@Priority(Priorities.AUTHENTICATION)
public class JWTTokenNeededFilter implements ContainerRequestFilter {
    @Context
    private ResourceInfo resourceInfo;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {

        // Get the HTTP Authorization header from the request
        String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);

        try {
            // Extract the token from the HTTP Authorization header
            String token = authorizationHeader.substring("Bearer".length()).trim();
            // Validate the token
            Claims claims =  Jwts.parser().setSigningKey("MYSECRET".getBytes("UTF-8")).parseClaimsJws(token).getBody();

            Method method =resourceInfo.getResourceMethod();
            if( method != null){
                // Get allowed permission on method
                JWTTokenNeeded JWTContext = method.getAnnotation(JWTTokenNeeded.class);
                Role permission =  JWTContext.Permissions();

                if(permission != Role.NoRights ) {
                    // Get Role from jwt
                    String roles = claims.get("Role", String.class);
                    Role roleUser = Role.valueOf(roles);

                    // if role allowed != role jwt -> UNAUTHORIZED
                    if (!permission.equals(roleUser)) {
                        throw new Exception("no roles");
                    }

                }
            }

        }
        catch (Exception e) {
            e.printStackTrace();
            requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
        }
    }
}

@JWTTokenNeeded接口:

@javax.ws.rs.NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface JWTTokenNeeded {
    Role Permissions() default Role.NoRights;
}

允许角色访问端点就像添加@JWTTokenNeeded(Permissions = Role.Admin)

这是一个示例:

@Path("User")
public class UserResource {
    @EJB
    private UserappDAO userDAO;


    @GET
    @JWTTokenNeeded(Permissions = Role.Admin)
    @Produces("application/json")
    public List<Userapp> all() {
        return userDAO.getAll();
    }
}