【问题标题】:Java Rest API JAX-RS URLJava Rest API JAX-RS URL
【发布时间】:2016-12-18 10:27:00
【问题描述】:

我有一个类似于以下代码的 Java 应用程序。我需要能够将用户名、密码和 url 传递给它来执行任务。 url 调用会是什么样子?

用户名将是一封电子邮件,因此:myemail@mail.com 密码只是一个字符串 网址将是:例如:hhtps://login.salesforce.com/services/Soap/u/37.0

到目前为止,我有这个网址,但它不起作用

localhost:8080/myAPP/webapi/myapi?user=some@email.com&pass=jsjjsd&url=hhtps://login.salesforce.com/services/Soap/u/37.0

类代码

@Path("/myapi")
public class myClass(){


@GET
@Path("/{user}/{pass}/{url}")
@Produces(MediaType.APPLICATION_JSON)
public String foo(@PathParam("user") String user,
                    @PathParam("pass") String pass,
                    @PathParam("url") String url) {
     return "test";
}

}

【问题讨论】:

  • 您确定要在 URL 中公开密码吗?幸运的是我没有使用你的 API!

标签: java rest tomcat jax-rs


【解决方案1】:

在 URL 中发送敏感数据是一个非常糟糕的主意。 永远不要这样做。 请求的 URL 由服务器和代理记录。如果浏览器请求 URL,则 URL 会转到浏览器历史记录。 这是一个安全漏洞。

你不应该做的事情

找出下面两个你绝对不能使用的不好的方法

如果你的端点是这样的:

@Path("/myapi")
public class MyResource() {

    @GET
    @Path("/{user}/{pass}/{url}")
    @Produces(MediaType.APPLICATION_JSON)
    public String foo(@PathParam("user") String user,
                      @PathParam("pass") String pass,
                      @PathParam("url") String url) {
         ...
    }
}

请求会是这样的:

GET /myAPP/webapi/myapi/some%40email.com/jsjjsd/https%3A%2F%2Flogin.salesforce.com%2Fservices%2FSoap%2Fu%2F37.0 HTTP/1.1
Host: localhost:8080
Accept: application/json

如果你的端点是这样的:

@Path("/myapi")
public class MyResource() {

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String foo(@QueryParam("user") String user,
                      @QueryParam("pass") String pass,
                      @QueryParam("url") String url) {
        ...
    }
}

请求会是这样的:

GET /myAPP/webapi/myapi?user=some%40email.com&pass=jsjjsd&url=https%3A%2F%2Flogin.salesforce.com%2Fservices%2FSoap%2Fu%2F37.0 HTTP/1.1
Host: localhost:8080
Accept: application/json

请注意参数值是 URL 编码的。如需进一步参考,请查看此answer

你应该怎么做

当通过网络发送敏感数据时,强烈建议使用 HTTPS。 HTTPS 将保护您免受中间人攻击。对于证书颁发机构,您可以考虑Let's Encrypt。它声称是免费、自动化和开放的。

您应该使用POST 在请求负载中发送它们,而不是在 URL 中发送这些参数。例如,请求有效负载可以是 JSON。使用 JAX-RS 后,您可以使用 JSON 提供程序,例如 Jackson。

为此,请定义一个如下所示的 bean:

public class Credentials implements Serializable {

    private String user;
    private String pass;
    private String url;

    // Getters and setters omitted
}

并在您的资源方法中使用它:

@Path("/myapi")
public class MyResource() {

    @POST
    @Consumer(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public String foo(Credentials credentials) {
        ...
    }
}

请求会是这样的:

POST /myAPP/webapi/myapi HTTP/1.1
Host: localhost:8080
Content-Type: application/json
Accept: application/json

{
  "user": "some@email.com",
  "pass": "jsjjsd",
  "url": "https://login.salesforce.com/services/Soap/u/37.0"
}

【讨论】:

    【解决方案2】:

    你必须改用QueryParam注解。

    示例:

    @Path("/myapi")
    public class myClass(){
    
        @GET
        @Produces(MediaType.APPLICATION_JSON)
        public String foo(@QueryParam("user") String user,
            @QueryParam("pass") String pass,
            @QueryParam("url") String url) {
            return "test";
        }
    }
    

    【讨论】:

    • 在 URL 中发送密码是一个非常糟糕的主意
    • 我同意。但这并不是解决方案是错误的。这只是意味着解决问题的方法是错误的。
    • 提供的解决方案部分正确:查询参数值必须经过 URL 编码。但请记住,这种方法很糟糕,不应鼓励 OP 走错路。
    【解决方案3】:

    您的网址不正确。在您的方法中,您正在定义 pathParams,但您的 url 有 queryParams。

    更改您的网址或方法。

    主要错误是您的实施。通过 URL 以纯文本形式发送凭据是一种糟糕的安全做法。考虑对密码使用任何加密并为您的应用程序管理令牌。登录的 URL 将由后端管理。考虑使用 POST 方法。

    看这个。 Best practice for REST token-based authentication with JAX-RS and Jersey

    问候

    【讨论】:

      猜你喜欢
      • 2017-11-12
      • 2015-04-25
      • 1970-01-01
      • 2012-06-26
      • 2015-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-08
      相关资源
      最近更新 更多