Dropwizard仅在@POST上验证字段 [英] Dropwizard validate a field only on @POST

查看:144
本文介绍了Dropwizard仅在@POST上验证字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这些只读字段需要是安全的,比如密码。假设我们有一个用户对象:

I have these read-only fields which needs to be secure, like passwords. Say we have a user object:

public class User {
  @NotEmpty
  @Size(max = 100)
  private String name;
  @NotEmpty
  private String username;
  @NotEmpty
  @Email
  private String email;
  private String password;

  @JsonIgnore
  public String getPassword() {
    return password;
  }

  @JsonProperty
  public void setPassword(String password) {
    this.password = password;
  }
}

所以,这很好用;就像我可以得到/发布/放置任何我想要的,但我永远不会收到密码。但我也想确保第一次发布时,密码不应为空。如果我这样做

So, this works nicely; as in I can get/post/put whatever I want, but I will never receive the password back. But I also want to make sure that when it's posted for the first time, password should not be empty. If I do

@NotEmpty
private string password;

如果我不想更改,那么我的PUT(编辑)请求将失败,并显示验证错误这个用户的密码。

Then my PUT (edit) requests will fail with validation error if I don't want to change the password of this user.

我能想到两种解决方案:

1 - 继承User类,只为POST创建一个特殊类,它可以在getter上有@NotEmpty注释。

1- Inherit User class, create a special class only for POST which can have the @NotEmpty annotation over the getter.

public static class Create extends User {
  @NotEmpty
  @Override
  public String getPassword() {
    return password;
  }
}

这应该可以正常工作,但不适用于我的代码库,因为它是已经在CRUD资源上大量使用继承。我需要为这种方法打破并复制很多东西。

This should work generally but not for my codebase as it's already utilizing inheritance greatly on CRUD resources. I'd need to break and duplicate a lot of things for this approach.

2 - 处理资源类的验证:

public class UserResource {

  @POST
  public User createUser(User user) {
    if(user.getPassword().isEmpty()) {
      throw new ConstraintValidation....();
    }
  }
}

这份工作,但不是真漂亮。特别是因为我有5-10个。

Does the job, but not so pretty. Especially since I have 5-10 of these.

还有其他选择吗?

推荐答案

除了针织衫注射和自定义验证器之外,我发现了一个更酷,更容易和更顺畅的解决方案,我认为您可能会对此感兴趣,Natan:

Apart from jersey injection and a custom validator, I found a cooler and easier and smoother solution I think that might interest you, Natan:

DW支持验证组代替。通过这些,您可以根据您的方法决定要注释的内容,而无需验证方法。你可以在这里阅读更多相关信息:

DW supports validation groups instead. With these, you can decide what to annotate based on your method, without the validation knowing about the method. You can read more about that here:

http://www.dropwizard.io/0.9.0/docs/manual/validation.html

(fwiw我是在我的例子中使用RC版本。)

(fwiw I am using the RC release in my example).

所以让我们开始吧:

@Path("/hello/world")
@Produces(MediaType.APPLICATION_JSON)
public class HelloWorldResource {

    @POST
    @Path("/v1")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response test(@Valid @Validated(V1Check.class) User user) {
        // checks only username
        System.out.println(user.getName());
        System.out.println(user.getPassword());

        return Response.ok().build();
    }


    @POST
    @Path("/v2")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response test2(@Valid @Validated(V2Check.class) User user) {
        // checks both
        System.out.println(user.getName());
        System.out.println(user.getPassword());

        return Response.ok().build();
    }
}

这是资源类。看看我如何用@Validated注释这两个方法。这告诉DW要准确验证什么。

This is the resource class. See how I annotated both methods with @Validated. This tells DW what to validate exactly.

这是我的用户类:

public class User {

    @JsonProperty("name")
    private String name;

    @JsonProperty("password")
    private String password;

    @NotEmpty(message="other message", groups= {V2Check.class} )
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @NotEmpty(message="asd asd asd", groups= {V1Check.class, V2Check.class } )
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public interface V1Check {};
    public interface V2Check {};
}

我也在该类中嵌入了接口。密码现在只有V2检查。因此,对于POST方法,您需要将其添加到Validated注释中,而get方法可以保持V1检查并忽略密码。

I embedded the interfaces in that class as well. Password is now only V2 checked. So for your POST method, you'll want to add that to the Validated annotation, while your get method can remain V1 checked and ignores the password.

为了更好的衡量,我的测试的首发:

And for good measure, the starter for my test:

public class Starter extends Application<Configuration> {

    @Override
    public void run(Configuration configuration, Environment environment) throws Exception {
        environment.jersey().register(HelloWorldResource.class);
    }

    public static void main(String[] args) throws Exception {
        new Starter().run("server", "/Users/artur/dev/repo/dw-test/src/main/resources/configuration.yaml");
    }

}

这是DW的做法但是,您应该能够将泽西注射添加到您的自定义验证器中。编写自定义验证器似乎没有必要,因为您不需要检查密码。

This is the DW way to do this, however you should be able to add jersey injection into your custom validators as well. It just seems unnecessary to write a custom validator JUST because you need to not check your passwords.

这是我的卷发。 user_json2:

Here's my curls. The user_json2:

{
    "name" : "artur"
}

V1,不检查密码:

arturk:tmp artur$ curl -XPOST "localhost:9085/hello/world/v1/" --header "Content-Type: application/json" -d @user_json2 -v
    *   Trying ::1...
    * Connected to localhost (::1) port 9085 (#0)
    > POST /hello/world/v1/ HTTP/1.1
    > Host: localhost:9085
    > User-Agent: curl/7.43.0
    > Accept: */*
    > Content-Type: application/json
    > Content-Length: 19
    >
    * upload completely sent off: 19 out of 19 bytes
    < HTTP/1.1 200 OK
    < Date: Fri, 27 May 2016 09:59:22 GMT
    < Content-Length: 0
    <
    * Connection #0 to host localhost left intact

V2,检查密码:

arturk:tmp artur$ curl -XPOST "localhost:9085/hello/world/v2/" --header "Content-Type: application/json" -d @user_json2 -v
*   Trying ::1...
* Connected to localhost (::1) port 9085 (#0)
> POST /hello/world/v2/ HTTP/1.1
> Host: localhost:9085
> User-Agent: curl/7.43.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 19
>
* upload completely sent off: 19 out of 19 bytes
< HTTP/1.1 400 Bad Request
< Date: Fri, 27 May 2016 10:07:41 GMT
< Content-Type: text/html;charset=iso-8859-1
< Cache-Control: must-revalidate,no-cache,no-store
< Content-Length: 251
<
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 400 Bad Request</title>
</head>
<body><h2>HTTP ERROR 400</h2>
<p>Problem accessing /hello/world/v2/. Reason:
<pre>    Bad Request</pre></p>
</body>
</html>
* Connection #0 to host localhost left intact

我希望有所帮助!

干杯,

Artur

这篇关于Dropwizard仅在@POST上验证字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆