【问题标题】:Role Based Authentication on Restful endpoints in javajava中Restful端点上基于角色的身份验证
【发布时间】:2019-08-28 18:28:04
【问题描述】:

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

我正在寻找一种在端点前简单添加:@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());

如果用户被授权,端点必须这样做。

【问题讨论】:

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


【解决方案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();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-25
    • 2016-01-03
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    • 2015-05-17
    • 1970-01-01
    • 2023-01-24
    相关资源
    最近更新 更多