Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
针对不同请求方法的Java httpServer基本身份验证_Java_Rest_Basic Authentication_Httpserver - Fatal编程技术网

针对不同请求方法的Java httpServer基本身份验证

针对不同请求方法的Java httpServer基本身份验证,java,rest,basic-authentication,httpserver,Java,Rest,Basic Authentication,Httpserver,我在Java中使用一个非常简单的httpServer作为api rest,其中包含GET、POST、PUT和DELETE。我使用的是基本身份验证,我有两个类Authentication.java和authorization.java,用于验证和检查用户的权限 所以,我希望所有用户(经过身份验证的)都能够从我的api rest中获取信息,但只有具有特定权限的用户才能发布、放置和删除。那我该怎么做呢 这就是我得到的 public class Server { private static Ht

我在Java中使用一个非常简单的httpServer作为api rest,其中包含GET、POST、PUT和DELETE。我使用的是基本身份验证,我有两个类Authentication.java和authorization.java,用于验证和检查用户的权限

所以,我希望所有用户(经过身份验证的)都能够从我的api rest中获取信息,但只有具有特定权限的用户才能发布、放置和删除。那我该怎么做呢

这就是我得到的

public class Server {

  private static HttpServer server;

  public static void start() throws IOException {

    server = HttpServer.create(new InetSocketAddress(8000), 0);
    HttpContext ctx = server.createContext("/users", new UserHandler());
    ctx.setAuthenticator(new ApiRestBasicAuthentication("users"));

    server.start();
  }

}
这是我最基本的证明

public class ApiRestBasicAuthentication extends BasicAuthenticator {

  private UserAuthentication authentication = new UserAuthentication();

  public ApiRestBasicAuthentication(String realm) {
    super(realm);
  }

  @Override
  public boolean checkCredentials(String user, String pwd) {
    int authCode = authentication.authenticate(user, pwd);
    return authCode == UserAuthentication.USER_AUTHENTICATED;
  }

}
现在,检查凭据只是检查用户是否经过身份验证。 但是我想检查,如果方法是POST、DELETE或PUT,我还应该检查具体的凭据。但是我怎样才能在我的ApiRestBasicAuthentication中获得该方法呢?我在我的处理程序类中这样做

public void handle(HttpExchange httpExchange) throws IOException {
    String method = httpExchange.getRequestMethod();
    if ("post".equalsIgnoreCase(method)) {
      createUser(httpExchange);
    } else if ("get".equalsIgnoreCase(method)) {
      readUsers(httpExchange);
    } else if ("put".equalsIgnoreCase(method)) {
      updateUser(httpExchange);
    } else if ("delete".equalsIgnoreCase(method)) {
      deleteUser(httpExchange);
    }
  }
也许这应该用另一种方式。 有什么想法吗


非常感谢。

解决这个问题的方法可能很多。以下是我的建议之一:

  • 创建一个用户对象,其中包含您想要的字段和一个名为“角色”的字段。假设只有“管理员”可以执行除“GET”之外的Http请求,而“普通”用户只能执行“GET”。有很多方法可以做到这一点,但有一种方法是使“角色”字段成为字符串,并使用枚举为其赋值,这样以后很容易更改,并且只使用特定的术语。但你不必这么做。为您创建的字段和以后可能需要的字段编写get和set方法,当然是为角色编写

  • 您需要确保包含句柄的类(HttpExchange-HttpExchange)能够看到当前登录的用户,并引用与其关联的用户对象。然后您需要修改该方法,以便


  • 由于还没有提供其他实现,我无法给出更详细的答案,也无法确定这是否适用于您

    一个简单的方法是改变你的 ApiRestBasicAuthentication,如:

    public class ApiRestBasicAuthentication extends BasicAuthenticator {
    
      private UserAuthentication authentication = new UserAuthentication();
    
      public ApiRestBasicAuthentication(String realm) {
        super(realm);
      }
    
      @Override
      public Authenticator.Result authenticate(HttpExchange exch) {
          Authenticator.Result result=super.authenticate(exch);
          if(result instanceof Authenticator.Success) {
              HttpPrincipal principal=((Authenticator.Success)result).getPrincipal();
              String requestMethod=exch.getRequestMethod();       
              if( ADD SOME LOGIC HERE FOR PRINCIPAL AND REQUEST METHOD) {
                  return new return new Authenticator.Failure(401);
              }
              return result;
    
          }
      }
    
      @Override
      public boolean checkCredentials(String user, String pwd) {
        int authCode = authentication.authenticate(user, pwd);
        return authCode == UserAuthentication.USER_AUTHENTICATED;
      }
    
    }
    
    并为您希望验证失败的请求/用户添加一些逻辑。我在这里向您展示了如何在authenticate方法中获取该方法,但是您需要指定凭据的类型


    另一个解决方案是,如果您检查BasicAuthenticator的源代码,您可以看到它是如何实现
    authenticate
    方法的,您可以以类似的方式创建自己的实现,而不是扩展BasicAuthenticator,并使用get方法,而不仅仅是用户名和密码。您可以看到源代码,我相信您将能够找到自己的方法;)


    通常在企业应用程序中,您可以使用一些外部安全管理系统——例如,如果您使用Spring(当前java web应用程序中的事实标准)您可以使用spring安全性,并以更具声明性的方式执行此类安全模式和过滤器

    我认为您应该创建一个
    AuthenticationInterceptor
    和旁路
    获取那里的请求,并相应地为rest
    非获取
    请求应用身份验证机制

    public class AuthenticationInterceptor extends HandlerInterceptorAdapter {
    
      @Autowired
      private ApiRestBasicAuthentication apiRestBasicAuthentication;
    
      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        switch (request.getMethod()) {
          case "GET" :
            // by-passing all GET requests
            return true;
    
          default :
            return apiRestBasicAuthentication.checkCredentials(username, password);
        }
      }
    
    }
    

    虽然上面的答案可能对您有效,但我认为您也应该考虑使用定义在Web.xml中的角色和安全约束,并使用ReleSead注释在REST资源中使用。然后,这允许您单独或在REST资源/类级别专门允许方法的权限

    在web.xml中,这类似于:-

    <security-role>
            <role-name>SERVERTOSERVER</role-name>
        </security-role>
        <security-constraint>
            <web-resource-collection>
                <web-resource-name>REST API description</web-resource-name>
                <url-pattern>/<path name>/*</url-pattern>
                <http-method>GET</http-method>
            </web-resource-collection>
            <auth-constraint>
                <description>Only allow users 
            from following roles</description>
                <role-name>SERVERTOSERVER</role-name>
            </auth-constraint>
        </security-constraint>
    
    
    服务器到服务器
    RESTAPI描述
    //*
    得到
    , 
    


    如果有帮助,这里有另一种针对基于Jersey的应用程序的解决方案:

    我想您需要一些授权方面(或过滤器或拦截器提供的类似功能),只有在用户获得授权的情况下才会响应非GET,尽管我现在无法帮您提供完整答案。找出哪些(方面、过滤器、拦截器)是可用的,并阅读相关内容。这可能会起作用,因为我可以检查过滤器中的方法(POST、GET、PUT等),但如何在过滤器中获取请求中发送的用户名?我的ApiRestBasicAuthentication有一个checkCredentials()函数,它接收用户和密码,但在过滤器中我只有httpExchange对象,并且用户名/密码是加密的。我建议您使用
    spring security
    。看看下面的答案:您指的是什么
    web.xml
    @RolesAllowed
    注释从何而来?在没有交叉检查的情况下,我假设您正在讨论一个特定于Tomcat服务器的解决方案。因此,这个答案不符合上面的问题。javax.annotation.security.RolesAllowed,我已经给出了一些基于角色访问(基于tomcat/jersey的RESTAPI)的示例,正如您自己所说,您的解决方案是基于tomcat/jersey的。因此,它不能与
    com.sun.net.HttpServer
    -包中的
    HttpServer
    (或
    HttpsServer
    )一起使用。@RolesAllowed是一个与安全角色一起使用的java注释。我怀疑你说的完全正确。
    <security-role>
            <role-name>SERVERTOSERVER</role-name>
        </security-role>
        <security-constraint>
            <web-resource-collection>
                <web-resource-name>REST API description</web-resource-name>
                <url-pattern>/<path name>/*</url-pattern>
                <http-method>GET</http-method>
            </web-resource-collection>
            <auth-constraint>
                <description>Only allow users 
            from following roles</description>
                <role-name>SERVERTOSERVER</role-name>
            </auth-constraint>
        </security-constraint>